diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..5c1ed394 --- /dev/null +++ b/.gitignore @@ -0,0 +1,9 @@ +target/mvn-eclipse-cache.properties +target/ + +# eclipse +.classpath +.project +.settings +.idea/ +*.iml diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 00000000..d9a95f5c --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,191 @@ +Apache License +Version 2.0, January 2004 +http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + +"License" shall mean the terms and conditions for use, reproduction, and +distribution as defined by Sections 1 through 9 of this document. + +"Licensor" shall mean the copyright owner or entity authorized by the copyright +owner that is granting the License. + +"Legal Entity" shall mean the union of the acting entity and all other entities +that control, are controlled by, or are under common control with that entity. +For the purposes of this definition, "control" means (i) the power, direct or +indirect, to cause the direction or management of such entity, whether by +contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the +outstanding shares, or (iii) beneficial ownership of such entity. + +"You" (or "Your") shall mean an individual or Legal Entity exercising +permissions granted by this License. + +"Source" form shall mean the preferred form for making modifications, including +but not limited to software source code, documentation source, and configuration +files. + +"Object" form shall mean any form resulting from mechanical transformation or +translation of a Source form, including but not limited to compiled object code, +generated documentation, and conversions to other media types. + +"Work" shall mean the work of authorship, whether in Source or Object form, made +available under the License, as indicated by a copyright notice that is included +in or attached to the work (an example is provided in the Appendix below). + +"Derivative Works" shall mean any work, whether in Source or Object form, that +is based on (or derived from) the Work and for which the editorial revisions, +annotations, elaborations, or other modifications represent, as a whole, an +original work of authorship. For the purposes of this License, Derivative Works +shall not include works that remain separable from, or merely link (or bind by +name) to the interfaces of, the Work and Derivative Works thereof. + +"Contribution" shall mean any work of authorship, including the original version +of the Work and any modifications or additions to that Work or Derivative Works +thereof, that is intentionally submitted to Licensor for inclusion in the Work +by the copyright owner or by an individual or Legal Entity authorized to submit +on behalf of the copyright owner. For the purposes of this definition, +"submitted" means any form of electronic, verbal, or written communication sent +to the Licensor or its representatives, including but not limited to +communication on electronic mailing lists, source code control systems, and +issue tracking systems that are managed by, or on behalf of, the Licensor for +the purpose of discussing and improving the Work, but excluding communication +that is conspicuously marked or otherwise designated in writing by the copyright +owner as "Not a Contribution." + +"Contributor" shall mean Licensor and any individual or Legal Entity on behalf +of whom a Contribution has been received by Licensor and subsequently +incorporated within the Work. + +2. Grant of Copyright License. + +Subject to the terms and conditions of this License, each Contributor hereby +grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, +irrevocable copyright license to reproduce, prepare Derivative Works of, +publicly display, publicly perform, sublicense, and distribute the Work and such +Derivative Works in Source or Object form. + +3. Grant of Patent License. + +Subject to the terms and conditions of this License, each Contributor hereby +grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, +irrevocable (except as stated in this section) patent license to make, have +made, use, offer to sell, sell, import, and otherwise transfer the Work, where +such license applies only to those patent claims licensable by such Contributor +that are necessarily infringed by their Contribution(s) alone or by combination +of their Contribution(s) with the Work to which such Contribution(s) was +submitted. If You institute patent litigation against any entity (including a +cross-claim or counterclaim in a lawsuit) alleging that the Work or a +Contribution incorporated within the Work constitutes direct or contributory +patent infringement, then any patent licenses granted to You under this License +for that Work shall terminate as of the date such litigation is filed. + +4. Redistribution. + +You may reproduce and distribute copies of the Work or Derivative Works thereof +in any medium, with or without modifications, and in Source or Object form, +provided that You meet the following conditions: + +You must give any other recipients of the Work or Derivative Works a copy of +this License; and +You must cause any modified files to carry prominent notices stating that You +changed the files; and +You must retain, in the Source form of any Derivative Works that You distribute, +all copyright, patent, trademark, and attribution notices from the Source form +of the Work, excluding those notices that do not pertain to any part of the +Derivative Works; and +If the Work includes a "NOTICE" text file as part of its distribution, then any +Derivative Works that You distribute must include a readable copy of the +attribution notices contained within such NOTICE file, excluding those notices +that do not pertain to any part of the Derivative Works, in at least one of the +following places: within a NOTICE text file distributed as part of the +Derivative Works; within the Source form or documentation, if provided along +with the Derivative Works; or, within a display generated by the Derivative +Works, if and wherever such third-party notices normally appear. The contents of +the NOTICE file are for informational purposes only and do not modify the +License. You may add Your own attribution notices within Derivative Works that +You distribute, alongside or as an addendum to the NOTICE text from the Work, +provided that such additional attribution notices cannot be construed as +modifying the License. +You may add Your own copyright statement to Your modifications and may provide +additional or different license terms and conditions for use, reproduction, or +distribution of Your modifications, or for any such Derivative Works as a whole, +provided Your use, reproduction, and distribution of the Work otherwise complies +with the conditions stated in this License. + +5. Submission of Contributions. + +Unless You explicitly state otherwise, any Contribution intentionally submitted +for inclusion in the Work by You to the Licensor shall be under the terms and +conditions of this License, without any additional terms or conditions. +Notwithstanding the above, nothing herein shall supersede or modify the terms of +any separate license agreement you may have executed with Licensor regarding +such Contributions. + +6. Trademarks. + +This License does not grant permission to use the trade names, trademarks, +service marks, or product names of the Licensor, except as required for +reasonable and customary use in describing the origin of the Work and +reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. + +Unless required by applicable law or agreed to in writing, Licensor provides the +Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, +including, without limitation, any warranties or conditions of TITLE, +NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are +solely responsible for determining the appropriateness of using or +redistributing the Work and assume any risks associated with Your exercise of +permissions under this License. + +8. Limitation of Liability. + +In no event and under no legal theory, whether in tort (including negligence), +contract, or otherwise, unless required by applicable law (such as deliberate +and grossly negligent acts) or agreed to in writing, shall any Contributor be +liable to You for damages, including any direct, indirect, special, incidental, +or consequential damages of any character arising as a result of this License or +out of the use or inability to use the Work (including but not limited to +damages for loss of goodwill, work stoppage, computer failure or malfunction, or +any and all other commercial damages or losses), even if such Contributor has +been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. + +While redistributing the Work or Derivative Works thereof, You may choose to +offer, and charge a fee for, acceptance of support, warranty, indemnity, or +other liability obligations and/or rights consistent with this License. However, +in accepting such obligations, You may act only on Your own behalf and on Your +sole responsibility, not on behalf of any other Contributor, and only if You +agree to indemnify, defend, and hold each Contributor harmless for any liability +incurred by, or claims asserted against, such Contributor by reason of your +accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work + +To apply the Apache License to your work, attach the following boilerplate +notice, with the fields enclosed by brackets "[]" replaced with your own +identifying information. (Don't include the brackets!) The text should be +enclosed in the appropriate comment syntax for the file format. We also +recommend that a file or class name and description of purpose be included on +the same "printed page" as the copyright notice for easier identification within +third-party archives. + + Copyright 2013 Alibaba Group Holding Limited + + Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/README b/README deleted file mode 100644 index e69de29b..00000000 diff --git a/README.md b/README.md index 3d586086..fa0d245f 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,41 @@ -RocketMQ -======== +### RocketMQ是什么? +RocketMQ是一款分布式、队列模型的消息中间件,具有以下特点: -It's a MQ +* 能够保证严格的消息顺序 +* 提供丰富的消息拉取模式 +* 高效的订阅者水平扩展能力 +* 实时的消息订阅机制 +* 亿级消息堆积能力 + + +---------- + +### 如何开始? +* [下载安装包](https://github.com/alibaba/RocketMQ/releases) +* [Quick Start](https://github.com/alibaba/RocketMQ/wiki/Quick-Start) +* [通过Wiki了解更多](https://github.com/alibaba/RocketMQ/wiki) + +---------- + +### 开源协议 +[Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.html) Copyright (C) 2010-2013 Alibaba Group Holding Limited + +---------- + +### 开发规范 +* 代码使用Eclipse代码样式格式化,提交代码前须格式化[rocketmq.java.code.style.xml](https://github.com/alibaba/RocketMQ/blob/master/docs/rocketmq.java.code.style.xml) +* Java源文件使用Unix换行、UTF-8文件编码 +* 请在git clone命令之前执行`git config --global core.autocrlf false`,确保本地代码使用Unix换行格式 +* 请在develop分支上开发 +* 每次提交须有Issue关联,可在git提交注释中增加`#issue号码`进行关联 + +---------- + +### 联系我们 + +* [向我们提交建议、BUG、寻求技术帮助](https://github.com/alibaba/RocketMQ/issues/new) +* 欢迎参与RocketMQ项目,只需在Github上fork、pull request即可。 +* [到新浪微博交流RocketMQ](http://q.weibo.com/1628465) +* 加入QQ群交流,5776652 + +---------- \ No newline at end of file diff --git a/benchmark/consumer.sh b/benchmark/consumer.sh new file mode 100644 index 00000000..a94a617d --- /dev/null +++ b/benchmark/consumer.sh @@ -0,0 +1,6 @@ +#!/bin/sh + +# +# $Id: consumer.sh 1831 2013-05-16 01:39:51Z shijia.wxr $ +# +sh ./runclass.sh com.alibaba.rocketmq.example.benchmark.Consumer $@ diff --git a/benchmark/runclass.sh b/benchmark/runclass.sh index 7a6f4c6b..5b638031 100644 --- a/benchmark/runclass.sh +++ b/benchmark/runclass.sh @@ -13,9 +13,9 @@ fi BASE_DIR=$(dirname $0)/.. CLASSPATH=.:${BASE_DIR}/conf:${CLASSPATH} -JAVA_OPT_1="-server -Xms4g -Xmx4g -Xmn1g -XX:PermSize=128m -XX:MaxPermSize=320m" +JAVA_OPT_1="-server -Xms1g -Xmx1g -Xmn256m -XX:PermSize=128m -XX:MaxPermSize=320m" JAVA_OPT_2="-XX:+UseConcMarkSweepGC -XX:+UseCMSCompactAtFullCollection -XX:CMSInitiatingOccupancyFraction=70 -XX:+CMSParallelRemarkEnabled -XX:SoftRefLRUPolicyMSPerMB=0 -XX:+CMSClassUnloadingEnabled -XX:SurvivorRatio=8 -XX:+DisableExplicitGC" -JAVA_OPT_3="-verbose:gc -Xloggc:${HOME}/metaq_gc.log -XX:+PrintGCDetails -XX:+PrintGCDateStamps" +JAVA_OPT_3="-verbose:gc -Xloggc:${HOME}/rocketmq_client_gc.log -XX:+PrintGCDetails -XX:+PrintGCDateStamps" JAVA_OPT_4="-XX:-OmitStackTraceInFastThrow" JAVA_OPT_5="-Djava.ext.dirs=${BASE_DIR}/lib" JAVA_OPT_6="-cp ${CLASSPATH}" diff --git a/benchmark/tproducer.sh b/benchmark/tproducer.sh new file mode 100644 index 00000000..f19d2c68 --- /dev/null +++ b/benchmark/tproducer.sh @@ -0,0 +1,6 @@ +#!/bin/sh + +# +# $Id: producer.sh 1831 2013-05-16 01:39:51Z shijia.wxr $ +# +sh ./runclass.sh com.alibaba.rocketmq.example.benchmark.TransactionProducer $@ diff --git a/bin/README.md b/bin/README.md new file mode 100644 index 00000000..fa19540e --- /dev/null +++ b/bin/README.md @@ -0,0 +1,34 @@ +### 操作系统调优 +在生产环境部署Broker前,必须要执行os.sh,对操作系统进行调优 + +**P.S: os.sh只能执行一次,需要sudo root权限** + +### 启动broker +* Unix平台 + + `nohup sh mqbroker &` + +* Windows平台(仅支持64位) + + `mqbroker.exe` + +### 关闭broker + sh mqshutdown broker + +### 启动Name Server +* Unix平台 + + `nohup sh mqnamesrv &` + +* Windows平台(仅支持64位) + + `mqnamesrv.exe` + +### 关闭Name Server + sh mqshutdown namesrv + +### 更新或创建Topic + sh mqadmin updateTopic -b 127.0.0.1:10911 -t TopicA + +### 更新或创建订阅组 + sh mqadmin updateSubGroup -b 127.0.0.1:10911 -g SubGroupA \ No newline at end of file diff --git a/bin/mqconsole b/bin/mqadmin similarity index 79% rename from bin/mqconsole rename to bin/mqadmin index 7a8ff9e1..67a94c7b 100644 --- a/bin/mqconsole +++ b/bin/mqadmin @@ -1,7 +1,7 @@ #!/bin/sh # -# $Id: mqbroker 1472 2013-04-17 06:51:11Z shijia.wxr $ +# $Id: mqbroker 1840 2013-05-16 02:13:59Z shijia.wxr $ # if [ -z "$ROCKETMQ_HOME" ] ; then @@ -31,4 +31,4 @@ fi export ROCKETMQ_HOME -sh ${ROCKETMQ_HOME}/bin/runserver.sh com.alibaba.rocketmq.console.ConsoleStartup $@ +sh ${ROCKETMQ_HOME}/bin/tools.sh com.alibaba.rocketmq.tools.command.MQAdminStartup $@ diff --git a/bin/mqadmin.exe b/bin/mqadmin.exe new file mode 100644 index 00000000..e8d8fac0 Binary files /dev/null and b/bin/mqadmin.exe differ diff --git a/bin/mqadmin.xml b/bin/mqadmin.xml new file mode 100644 index 00000000..560a8e5a --- /dev/null +++ b/bin/mqadmin.xml @@ -0,0 +1,26 @@ + + false + + ${JAVA_HOME} + + server + + com.alibaba.rocketmq.tools.command.MQAdminStartup + + + ${cpd}/../lib + ${cpd}/.. + + + + + + + <-Xms512m> + <-Xmx1g> + <-XX:NewSize>256M + <-XX:MaxNewSize>512M + <-XX:PermSize>128M + <-XX:MaxPermSize>128M + + diff --git a/bin/mqbroker.exe b/bin/mqbroker.exe new file mode 100644 index 00000000..e8d8fac0 Binary files /dev/null and b/bin/mqbroker.exe differ diff --git a/bin/mqbroker.xml b/bin/mqbroker.xml new file mode 100644 index 00000000..0cd31d6b --- /dev/null +++ b/bin/mqbroker.xml @@ -0,0 +1,26 @@ + + false + + ${JAVA_HOME} + + server + + com.alibaba.rocketmq.broker.BrokerStartup + + + ${cpd}/../lib + ${cpd}/.. + + + + + + + <-Xms512m> + <-Xmx1g> + <-XX:NewSize>256M + <-XX:MaxNewSize>512M + <-XX:PermSize>128M + <-XX:MaxPermSize>128M + + diff --git a/bin/mqnamesrv.exe b/bin/mqnamesrv.exe new file mode 100644 index 00000000..e8d8fac0 Binary files /dev/null and b/bin/mqnamesrv.exe differ diff --git a/bin/mqnamesrv.xml b/bin/mqnamesrv.xml new file mode 100644 index 00000000..c9701ccf --- /dev/null +++ b/bin/mqnamesrv.xml @@ -0,0 +1,26 @@ + + false + + ${JAVA_HOME} + + server + + com.alibaba.rocketmq.namesrv.NamesrvStartup + + + ${cpd}/../lib + ${cpd}/.. + + + + + + + <-Xms512m> + <-Xmx1g> + <-XX:NewSize>256M + <-XX:MaxNewSize>512M + <-XX:PermSize>128M + <-XX:MaxPermSize>128M + + diff --git a/bin/mqshutdown b/bin/mqshutdown index d72dfa5b..6a3b6ff7 100644 --- a/bin/mqshutdown +++ b/bin/mqshutdown @@ -1,17 +1,34 @@ #!/bin/sh -# -# $Id: mqshutdown 1831 2013-05-16 01:39:51Z shijia.wxr $ -# +case $1 in + broker) -pid=`ps ax | grep -i 'com.alibaba.rocketmq.broker.BrokerStartup' |grep java | grep -v grep | awk '{print $1}'` -if [ -z "$pid" ] ; then - echo "No mqbroker running." - exit -1; -fi + pid=`ps ax | grep -i 'com.alibaba.rocketmq.broker.BrokerStartup' |grep java | grep -v grep | awk '{print $1}'` + if [ -z "$pid" ] ; then + echo "No mqbroker running." + exit -1; + fi -echo "The mqbroker(${pid}) is running..." + echo "The mqbroker(${pid}) is running..." -kill ${pid} + kill ${pid} -echo "Send shutdown request to mqbroker(${pid}) OK" + echo "Send shutdown request to mqbroker(${pid}) OK" + ;; + namesrv) + + pid=`ps ax | grep -i 'com.alibaba.rocketmq.namesrv.NamesrvStartup' |grep java | grep -v grep | awk '{print $1}'` + if [ -z "$pid" ] ; then + echo "No mqnamesrv running." + exit -1; + fi + + echo "The mqnamesrv(${pid}) is running..." + + kill ${pid} + + echo "Send shutdown request to mqnamesrv(${pid}) OK" + ;; + *) + echo "Useage: mqshutdown broker | namesrv" +esac diff --git a/bin/os.sh b/bin/os.sh index aec5be64..372a0bb2 100644 --- a/bin/os.sh +++ b/bin/os.sh @@ -1,47 +1,40 @@ #!/bin/sh -sudo sysctl vm.overcommit_memory=1 -sudo sysctl vm.min_free_kbytes=5000000 -sudo sysctl vm.drop_caches=1 -sudo sysctl vm.zone_reclaim_mode=0 -sudo sysctl vm.max_map_count=655360 -sudo sysctl vm.dirty_background_ratio=50 -sudo sysctl vm.dirty_ratio=50 -sudo sysctl vm.page-cluster=3 -sudo sysctl vm.dirty_writeback_centisecs=360000 -sudo sysctl vm.swappiness=10 +# +# Execute Only Once +# -NOFILE=`ulimit -n` -echo "nofile=${NOFILE}" +echo 'vm.overcommit_memory=1' >> /etc/sysctl.conf +echo 'vm.min_free_kbytes=5000000' >> /etc/sysctl.conf +echo 'vm.drop_caches=1' >> /etc/sysctl.conf +echo 'vm.zone_reclaim_mode=0' >> /etc/sysctl.conf +echo 'vm.max_map_count=655360' >> /etc/sysctl.conf +echo 'vm.dirty_background_ratio=50' >> /etc/sysctl.conf +echo 'vm.dirty_ratio=50' >> /etc/sysctl.conf +echo 'vm.page-cluster=3' >> /etc/sysctl.conf +echo 'vm.dirty_writeback_centisecs=360000' >> /etc/sysctl.conf +echo 'vm.swappiness=10' >> /etc/sysctl.conf +sysctl -p -if [ -d /sys/block/sda ]; then - SCHEDULER=`cat /sys/block/sda/queue/scheduler` - READ_AHEAD_KB=`cat /sys/block/sda/queue/read_ahead_kb` - echo "/sys/block/sda/queue/scheduler=${SCHEDULER}" - echo "/sys/block/sda/queue/read_ahead_kb=${READ_AHEAD_KB}" -fi +echo 'ulimit -n 655350' >> /etc/profile +echo 'admin hard nofile 655350' >> /etc/security/limits.conf -if [ -d /sys/block/sdb ]; then - SCHEDULER=`cat /sys/block/sdb/queue/scheduler` - READ_AHEAD_KB=`cat /sys/block/sdb/queue/read_ahead_kb` - echo "/sys/block/sdb/queue/scheduler=${SCHEDULER}" - echo "/sys/block/sdb/queue/read_ahead_kb=${READ_AHEAD_KB}" -fi +DISK=`df -k | sort -n -r -k 2 | awk -F/ 'NR==1 {gsub(/[0-9].*/,"",$3); print $3}'` +[ "$DISK" = 'cciss' ] && DISK='cciss!c0d0' +echo 'deadline' > /sys/block/$DISK/queue/scheduler -if [ -d /sys/block/sdc ]; then - SCHEDULER=`cat /sys/block/sdc/queue/scheduler` - READ_AHEAD_KB=`cat /sys/block/sdc/queue/read_ahead_kb` - echo "/sys/block/sdc/queue/scheduler=${SCHEDULER}" - echo "/sys/block/sdc/queue/read_ahead_kb=${READ_AHEAD_KB}" -fi -if [ -d /sys/block/sdd ]; then - SCHEDULER=`cat /sys/block/sdd/queue/scheduler` - READ_AHEAD_KB=`cat /sys/block/sdd/queue/read_ahead_kb` - echo "/sys/block/sdd/queue/scheduler=${SCHEDULER}" - echo "/sys/block/sdd/queue/read_ahead_kb=${READ_AHEAD_KB}" -fi +echo "---------------------------------------------------------------" +sysctl vm.overcommit_memory +sysctl vm.min_free_kbytes +sysctl vm.drop_caches +sysctl vm.zone_reclaim_mode +sysctl vm.max_map_count +sysctl vm.dirty_background_ratio +sysctl vm.dirty_ratio +sysctl vm.page-cluster +sysctl vm.dirty_writeback_centisecs +sysctl vm.swappiness -echo -echo "TODO: Change 'nofile' value in /etc/security/limits.conf" -echo "TODO: Change io scheduler value to deadline" +su - admin -c 'ulimit -n' +cat /sys/block/$DISK/queue/scheduler diff --git a/bin/runbroker.sh b/bin/runbroker.sh index 4cabcf9e..fdac09d1 100644 --- a/bin/runbroker.sh +++ b/bin/runbroker.sh @@ -15,7 +15,7 @@ CLASSPATH=.:${BASE_DIR}/conf:${CLASSPATH} JAVA_OPT_1="-server -Xms4g -Xmx4g -Xmn2g -XX:PermSize=128m -XX:MaxPermSize=320m" JAVA_OPT_2="-XX:+UseConcMarkSweepGC -XX:+UseCMSCompactAtFullCollection -XX:CMSInitiatingOccupancyFraction=70 -XX:+CMSParallelRemarkEnabled -XX:SoftRefLRUPolicyMSPerMB=0 -XX:+CMSClassUnloadingEnabled -XX:SurvivorRatio=8 -XX:+DisableExplicitGC" -JAVA_OPT_3="-verbose:gc -Xloggc:${HOME}/rocketmq_gc.log -XX:+PrintGCDetails -XX:+PrintGCDateStamps" +JAVA_OPT_3="-verbose:gc -Xloggc:${HOME}/rocketmq_gc.log -XX:+PrintGCDetails" JAVA_OPT_4="-XX:-OmitStackTraceInFastThrow" JAVA_OPT_5="-Djava.ext.dirs=${BASE_DIR}/lib" #JAVA_OPT_6="-Xdebug -Xrunjdwp:transport=dt_socket,address=9555,server=y,suspend=n" @@ -29,4 +29,10 @@ JAVA="$JAVA_HOME/bin/java" JAVA_OPTS="${JAVA_OPT_1} ${JAVA_OPT_2} ${JAVA_OPT_3} ${JAVA_OPT_4} ${JAVA_OPT_5} ${JAVA_OPT_6} ${JAVA_OPT_7}" -numactl --interleave=all $JAVA $JAVA_OPTS $@ +numactl --interleave=all pwd > /dev/null +if [ $? -eq 0 ] +then + numactl --interleave=all $JAVA $JAVA_OPTS $@ +else + $JAVA $JAVA_OPTS $@ +fi diff --git a/bin/runserver.sh b/bin/runserver.sh index ca17a7ef..fc7ab2ac 100644 --- a/bin/runserver.sh +++ b/bin/runserver.sh @@ -15,7 +15,7 @@ CLASSPATH=.:${BASE_DIR}/conf:${CLASSPATH} JAVA_OPT_1="-server -Xms4g -Xmx4g -Xmn2g -XX:PermSize=128m -XX:MaxPermSize=320m" JAVA_OPT_2="-XX:+UseConcMarkSweepGC -XX:+UseCMSCompactAtFullCollection -XX:CMSInitiatingOccupancyFraction=70 -XX:+CMSParallelRemarkEnabled -XX:SoftRefLRUPolicyMSPerMB=0 -XX:+CMSClassUnloadingEnabled -XX:SurvivorRatio=8 -XX:+DisableExplicitGC" -JAVA_OPT_3="-verbose:gc -Xloggc:${HOME}/rocketmq_gc.log -XX:+PrintGCDetails -XX:+PrintGCDateStamps" +JAVA_OPT_3="-verbose:gc -Xloggc:${HOME}/rocketmq_gc.log -XX:+PrintGCDetails" JAVA_OPT_4="-XX:-OmitStackTraceInFastThrow" JAVA_OPT_5="-Djava.ext.dirs=${BASE_DIR}/lib" #JAVA_OPT_6="-Xdebug -Xrunjdwp:transport=dt_socket,address=9555,server=y,suspend=n" diff --git a/build.sh b/build.sh new file mode 100644 index 00000000..432e372d --- /dev/null +++ b/build.sh @@ -0,0 +1,117 @@ +#!/bin/sh +PROG_NAME=rocketmq +SHELL_PATH=$(cd "$(dirname "$0")"; pwd) +#NS="10.232.26.122 10.232.25.81" +BROKER="10.232.25.82 10.232.25.83" +NS="10.232.26.122" +#BROKER="10.232.25.82" +NS_PORT=9876 +TGZ_NAME=alibaba-rocketmq-3.0.0-SNAPSHOT.tar.gz + +usage() { + echo "Usage: ${PROG_NAME} {package|dispatch|start|stop|ns|broker|cleanlog|cleanstore|clean|show}" + exit 1; +} + +package(){ + echo "############################# package #################################" + sh develop.sh +} + +dispatch(){ + echo "############################# dispatch #################################" + pgmscp -b ${NS} ${BROKER} target/${TGZ_NAME} /home/manhong.yqd + pgm -b ${NS} ${BROKER} "tar zxvf ${TGZ_NAME}" + pgm -b ${NS} ${BROKER} 'rm -rf devenv' + pgm -b ${NS} ${BROKER} 'mv alibaba-rocketmq devenv' + pgm -b ${NS} ${BROKER} 'chmod +x devenv/bin/*' + pgm -b ${NS} ${BROKER} 'sed -i s/#JAVA_OPT_6=/JAVA_OPT_6=/g devenv/bin/runbroker.sh' + pgm -b ${NS} ${BROKER} 'sed -i s/#JAVA_OPT_6=/JAVA_OPT_6=/g devenv/bin/runserver.sh' +} + +startup_ns(){ + echo "############################# startup nameserver #################################" + pgm -b ${NS} 'killall -9 java' + sleep 1 + pgm -b ${NS} 'rm -rf rocketmqlogs' + pgm -b ${NS} './devenv/bin/mqnamesrv' & + sleep 1 + pgm -b ${NS} 'ps -ef|grep java' + sleep 1 + pgm -b ${NS} "netstat -an|grep ${NS_PORT}" +} + +startup_broker(){ + echo "############################# startup broker #################################" + pgm -b ${BROKER} 'killall -9 java' + sleep 1 + pgm -b ${BROKER} 'rm -rf rocketmqlogs' + tmp=`echo ${NS} | sed "s/ /:${NS_PORT};/g"`":${NS_PORT}" + echo "nameserver:${tmp}" + pgm -b ${BROKER} "./devenv/bin/mqbroker -n '${tmp}'" & + sleep 1 + pgm -b ${BROKER} 'ps -ef|grep java' + sleep 1 + pgm -b ${BROKER} "netstat -an|grep '${NS_PORT}'" +} + +start(){ + startup_ns + startup_broker +} + +stop(){ + pgm -b ${NS} ${BROKER} 'killall -9 java' +} + +cleanlog(){ + echo "############################# startup log #################################" + pgm -b ${NS} ${BROKER} 'rm -rf rocketmqlogs' +} + +cleanstore(){ + echo "############################# clean store #################################" + pgm -b ${NS} ${BROKER} 'rm -rf store' +} + +show(){ + pgm -b ${NS} ${BROKER} 'ps -ef|grep java' + pgm -b ${NS} ${BROKER} "netstat -an|grep '${NS_PORT}'" +} + +case "$1" in + package) + package + ;; + dispatch) + dispatch + ;; + start) + start + ;; + stop) + stop + ;; + ns) + startup_ns + ;; + broker) + startup_broker + ;; + cleanlog) + cleanlog + ;; + cleanstore) + cleanstore + ;; + clean) + cleanlog + cleanstore + ;; + show) + show + ;; + *) + usage + ;; +esac diff --git a/conf/2m-2s-async/broker-a-s.properties b/conf/2m-2s-async/broker-a-s.properties new file mode 100644 index 00000000..254fdddb --- /dev/null +++ b/conf/2m-2s-async/broker-a-s.properties @@ -0,0 +1,7 @@ +brokerClusterName=DefaultCluster +brokerName=broker-a +brokerId=1 +deleteWhen=04 +fileReservedTime=48 +brokerRole=SLAVE +flushDiskType=ASYNC_FLUSH diff --git a/conf/2m-2s-async/broker-a.properties b/conf/2m-2s-async/broker-a.properties new file mode 100644 index 00000000..275aeb68 --- /dev/null +++ b/conf/2m-2s-async/broker-a.properties @@ -0,0 +1,7 @@ +brokerClusterName=DefaultCluster +brokerName=broker-a +brokerId=0 +deleteWhen=04 +fileReservedTime=48 +brokerRole=ASYNC_MASTER +flushDiskType=ASYNC_FLUSH diff --git a/conf/2m-2s-async/broker-b-s.properties b/conf/2m-2s-async/broker-b-s.properties new file mode 100644 index 00000000..2cd3357d --- /dev/null +++ b/conf/2m-2s-async/broker-b-s.properties @@ -0,0 +1,7 @@ +brokerClusterName=DefaultCluster +brokerName=broker-b +brokerId=1 +deleteWhen=04 +fileReservedTime=48 +brokerRole=SLAVE +flushDiskType=ASYNC_FLUSH diff --git a/conf/2m-2s-async/broker-b.properties b/conf/2m-2s-async/broker-b.properties new file mode 100644 index 00000000..0a116c04 --- /dev/null +++ b/conf/2m-2s-async/broker-b.properties @@ -0,0 +1,7 @@ +brokerClusterName=DefaultCluster +brokerName=broker-b +brokerId=0 +deleteWhen=04 +fileReservedTime=48 +brokerRole=ASYNC_MASTER +flushDiskType=ASYNC_FLUSH diff --git a/conf/2m-2s-sync/broker-a-s.properties b/conf/2m-2s-sync/broker-a-s.properties new file mode 100644 index 00000000..254fdddb --- /dev/null +++ b/conf/2m-2s-sync/broker-a-s.properties @@ -0,0 +1,7 @@ +brokerClusterName=DefaultCluster +brokerName=broker-a +brokerId=1 +deleteWhen=04 +fileReservedTime=48 +brokerRole=SLAVE +flushDiskType=ASYNC_FLUSH diff --git a/conf/2m-2s-sync/broker-a.properties b/conf/2m-2s-sync/broker-a.properties new file mode 100644 index 00000000..06d2d6f3 --- /dev/null +++ b/conf/2m-2s-sync/broker-a.properties @@ -0,0 +1,7 @@ +brokerClusterName=DefaultCluster +brokerName=broker-a +brokerId=0 +deleteWhen=04 +fileReservedTime=48 +brokerRole=SYNC_MASTER +flushDiskType=ASYNC_FLUSH diff --git a/conf/2m-2s-sync/broker-b-s.properties b/conf/2m-2s-sync/broker-b-s.properties new file mode 100644 index 00000000..2cd3357d --- /dev/null +++ b/conf/2m-2s-sync/broker-b-s.properties @@ -0,0 +1,7 @@ +brokerClusterName=DefaultCluster +brokerName=broker-b +brokerId=1 +deleteWhen=04 +fileReservedTime=48 +brokerRole=SLAVE +flushDiskType=ASYNC_FLUSH diff --git a/conf/2m-2s-sync/broker-b.properties b/conf/2m-2s-sync/broker-b.properties new file mode 100644 index 00000000..1ca35e6b --- /dev/null +++ b/conf/2m-2s-sync/broker-b.properties @@ -0,0 +1,7 @@ +brokerClusterName=DefaultCluster +brokerName=broker-b +brokerId=0 +deleteWhen=04 +fileReservedTime=48 +brokerRole=SYNC_MASTER +flushDiskType=ASYNC_FLUSH diff --git a/conf/2m-noslave/broker-a.properties b/conf/2m-noslave/broker-a.properties new file mode 100644 index 00000000..275aeb68 --- /dev/null +++ b/conf/2m-noslave/broker-a.properties @@ -0,0 +1,7 @@ +brokerClusterName=DefaultCluster +brokerName=broker-a +brokerId=0 +deleteWhen=04 +fileReservedTime=48 +brokerRole=ASYNC_MASTER +flushDiskType=ASYNC_FLUSH diff --git a/conf/2m-noslave/broker-b.properties b/conf/2m-noslave/broker-b.properties new file mode 100644 index 00000000..0a116c04 --- /dev/null +++ b/conf/2m-noslave/broker-b.properties @@ -0,0 +1,7 @@ +brokerClusterName=DefaultCluster +brokerName=broker-b +brokerId=0 +deleteWhen=04 +fileReservedTime=48 +brokerRole=ASYNC_MASTER +flushDiskType=ASYNC_FLUSH diff --git a/conf/log4j_tools.xml b/conf/log4j_tools.xml deleted file mode 100644 index 129e3e79..00000000 --- a/conf/log4j_tools.xml +++ /dev/null @@ -1,45 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/conf/logback_broker.xml b/conf/logback_broker.xml new file mode 100644 index 00000000..ad30f40e --- /dev/null +++ b/conf/logback_broker.xml @@ -0,0 +1,285 @@ + + + + ${user.home}/logs/rocketmqlogs/broker_default.log + true + + ${user.home}/logs/rocketmqlogs/otherdays/bk_default-%d{yyyy-MM-dd}.%i.log + + + 104857600 + + 10 + + + %d{yyy-MM-dd HH:mm:ss,GMT+8} %p %t - %m%n + UTF-8 + + + + + ${user.home}/logs/rocketmqlogs/broker.log + true + + ${user.home}/logs/rocketmqlogs/otherdays/broker-%d{yyyy-MM-dd}.%i.log + + + 104857600 + + 10 + + + %d{yyy-MM-dd HH:mm:ss,GMT+8} %p %t - %m%n + UTF-8 + + + + + ${user.home}/logs/rocketmqlogs/transaction.log + true + + ${user.home}/logs/rocketmqlogs/otherdays/transaction-%d{yyyy-MM-dd}.%i.log + + + 104857600 + + 10 + + + %d{yyy-MM-dd HH:mm:ss,GMT+8} %p %t - %m%n + UTF-8 + + + + + ${user.home}/logs/rocketmqlogs/lock.log + true + + ${user.home}/logs/rocketmqlogs/otherdays/lock-%d{yyyy-MM-dd}.%i.log + + + 104857600 + + 10 + + + %d{yyy-MM-dd HH:mm:ss,GMT+8} %p %t - %m%n + UTF-8 + + + + + ${user.home}/logs/rocketmqlogs/put.log + true + + ${user.home}/logs/rocketmqlogs/otherdays/put-%d{yyyy-MM-dd}.%i.log + + + 104857600 + + 10 + + + %d{yyy-MM-dd HH:mm:ss,GMT+8} %p %t - %m%n + UTF-8 + + + + + ${user.home}/logs/rocketmqlogs/get.log + true + + ${user.home}/logs/rocketmqlogs/otherdays/get-%d{yyyy-MM-dd}.%i.log + + + 104857600 + + 10 + + + %d{yyy-MM-dd HH:mm:ss,GMT+8} %p %t - %m%n + UTF-8 + + + + + ${user.home}/logs/rocketmqlogs/store.log + true + + ${user.home}/logs/rocketmqlogs/otherdays/store-%d{yyyy-MM-dd}.%i.log + + + 104857600 + + 10 + + + %d{yyy-MM-dd HH:mm:ss,GMT+8} %p %t - %m%n + UTF-8 + + + + + ${user.home}/logs/rocketmqlogs/pullmsgLive.log + true + + ${user.home}/logs/rocketmqlogs/otherdays/pullmsgLive-%d{yyyy-MM-dd}.%i.log + + + 104857600 + + 10 + + + %d{yyy-MM-dd HH:mm:ss,GMT+8} %p %t - %m%n + UTF-8 + + + + ${user.home}/logs/rocketmqlogs/putmsgLive.log + true + + ${user.home}/logs/rocketmqlogs/otherdays/putmsgLive-%d{yyyy-MM-dd}.%i.log + + + 104857600 + + 10 + + + %d{yyy-MM-dd HH:mm:ss,GMT+8} %p %t - %m%n + UTF-8 + + + + ${user.home}/logs/rocketmqlogs/sendbackmsgLive.log + true + + ${user.home}/logs/rocketmqlogs/otherdays/sendbackmsgLive-%d{yyyy-MM-dd}.%i.log + + + 104857600 + + 10 + + + %d{yyy-MM-dd HH:mm:ss,GMT+8} %p %t - %m%n + UTF-8 + + + + ${user.home}/logs/rocketmqlogs/updateCommitOffset.log + true + + ${user.home}/logs/rocketmqlogs/otherdays/updateCommitOffset-%d{yyyy-MM-dd}.%i.log + + + 104857600 + + 10 + + + %d{yyy-MM-dd HH:mm:ss,GMT+8} %p %t - %m%n + UTF-8 + + + + + true + + %d{yyy-MM-dd HH\:mm\:ss,GMT+8} %p %t - %m%n + UTF-8 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/conf/log4j_namesrv.xml b/conf/logback_namesrv.xml similarity index 56% rename from conf/log4j_namesrv.xml rename to conf/logback_namesrv.xml index cec3941c..9043bdc6 100644 --- a/conf/log4j_namesrv.xml +++ b/conf/logback_namesrv.xml @@ -1,34 +1,43 @@ - - ${user.home}/rocketmqlogs/rocketmq_default.log + + ${user.home}/logs/rocketmqlogs/namesrv_default.log true - rocketmq_default-%d{yyyy-MM-dd}.%i.log - - 33554432 + ${user.home}/logs/rocketmqlogs/otherdays/ns_default-%d{yyyy-MM-dd}.%i.log + + + 104857600 + 10 - %d{yyy-MM-dd HH\:mm\:ss,SSS} %p %t - %m%n + %d{yyy-MM-dd HH:mm:ss,GMT+8} %p %t - %m%n UTF-8 - - ${user.home}/rocketmqlogs/rocketmq_namesrv.log + + ${user.home}/logs/rocketmqlogs/namesrv.log true - rocketmq_namesrv-%d{yyyy-MM-dd}.%i.log - - 33554432 + ${user.home}/logs/rocketmqlogs/otherdays/namesrv-%d{yyyy-MM-dd}.%i.log + + + 104857600 + 10 - %d{yyy-MM-dd HH\:mm\:ss,SSS} %p %t - %m%n + %d{yyy-MM-dd HH:mm:ss,GMT+8} %p %t - %m%n UTF-8 + true @@ -36,6 +45,7 @@ UTF-8 + diff --git a/conf/log4j_broker.xml b/conf/logback_tools.xml similarity index 60% rename from conf/log4j_broker.xml rename to conf/logback_tools.xml index d7ce91c9..3712d5cd 100644 --- a/conf/log4j_broker.xml +++ b/conf/logback_tools.xml @@ -1,13 +1,17 @@ - - ${user.home}/rocketmqlogs/rocketmq_default.log + + ${user.home}/logs/rocketmqlogs/tools_default.log true - ${user.home}/rocketmqlogs/otherdays/rocketmq_default-%d{yyyy-MM-dd}.%i.log - - 33554432 + ${user.home}/logs/rocketmqlogs/otherdays/tl_default-%d{yyyy-MM-dd}.%i.log + + + 104857600 + 10 %d{yyy-MM-dd HH:mm:ss,GMT+8} %p %t - %m%n @@ -15,20 +19,25 @@ - - ${user.home}/rocketmqlogs/rocketmq_broker.log + + ${user.home}/logs/rocketmqlogs/tools.log true - ${user.home}/rocketmqlogs/otherdays/rocketmq_broker-%d{yyyy-MM-dd}.%i.log - - 33554432 + ${user.home}/logs/rocketmqlogs/otherdays/tools-%d{yyyy-MM-dd}.%i.log + + + 104857600 + 10 %d{yyy-MM-dd HH:mm:ss,GMT+8} %p %t - %m%n UTF-8 + true @@ -36,9 +45,10 @@ UTF-8 - + + - + diff --git a/conf/namesrv.properties b/conf/namesrv.properties deleted file mode 100644 index 2f68fd75..00000000 --- a/conf/namesrv.properties +++ /dev/null @@ -1,3 +0,0 @@ -# namesrv listen port -listenPort=9876 -namesrvAddr=10.235.136.47:9876;10.235.136.49:9876;10.235.144.44:9876 \ No newline at end of file diff --git a/deploy.bat b/deploy.bat new file mode 100644 index 00000000..b3334f03 --- /dev/null +++ b/deploy.bat @@ -0,0 +1 @@ +mvn -Dmaven.test.skip=true deploy \ No newline at end of file diff --git a/develop.sh b/develop.sh new file mode 100644 index 00000000..329e4393 --- /dev/null +++ b/develop.sh @@ -0,0 +1,15 @@ +git pull + +git checkout develop + +rm -rf target +rm -f devenv + +if [ -z "$JAVA_HOME" ]; then + JAVA_HOME=/opt/taobao/java +fi + +export PATH=/opt/taobao/mvn/bin:$JAVA_HOME/bin:$PATH +mvn -Dmaven.test.skip=true clean package install assembly:assembly -U + +ln -s target/alibaba-rocketmq-3.0.8-SNAPSHOT.dir/alibaba-rocketmq devenv diff --git a/docs/RocketMQ Benchmark case.xlsx b/docs/RocketMQ Benchmark case.xlsx deleted file mode 100644 index 68ffd355..00000000 Binary files a/docs/RocketMQ Benchmark case.xlsx and /dev/null differ diff --git a/docs/RocketMQ Benchmark.docx b/docs/RocketMQ Benchmark.docx deleted file mode 100644 index 073c364e..00000000 Binary files a/docs/RocketMQ Benchmark.docx and /dev/null differ diff --git a/docs/RocketMQ Share.pptx b/docs/RocketMQ Share.pptx deleted file mode 100644 index 6bafa7da..00000000 Binary files a/docs/RocketMQ Share.pptx and /dev/null differ diff --git "a/docs/RocketMQ \345\216\237\347\220\206\344\270\216\345\272\224\347\224\250.docx" "b/docs/RocketMQ \345\216\237\347\220\206\344\270\216\345\272\224\347\224\250.docx" deleted file mode 100644 index dc6042e8..00000000 Binary files "a/docs/RocketMQ \345\216\237\347\220\206\344\270\216\345\272\224\347\224\250.docx" and /dev/null differ diff --git "a/docs/RocketMQ \345\220\204\347\247\215\345\233\276\350\241\250.vsd" "b/docs/RocketMQ \345\220\204\347\247\215\345\233\276\350\241\250.vsd" deleted file mode 100644 index 08cc5c2f..00000000 Binary files "a/docs/RocketMQ \345\220\204\347\247\215\345\233\276\350\241\250.vsd" and /dev/null differ diff --git "a/docs/RocketMQ \346\212\200\346\234\257\346\226\271\346\241\210.pptx" "b/docs/RocketMQ \346\212\200\346\234\257\346\226\271\346\241\210.pptx" deleted file mode 100644 index 678482c7..00000000 Binary files "a/docs/RocketMQ \346\212\200\346\234\257\346\226\271\346\241\210.pptx" and /dev/null differ diff --git "a/docs/RocketMQ \350\241\250\346\240\274.xlsx" "b/docs/RocketMQ \350\241\250\346\240\274.xlsx" deleted file mode 100644 index 169e562b..00000000 Binary files "a/docs/RocketMQ \350\241\250\346\240\274.xlsx" and /dev/null differ diff --git "a/docs/RocketMQ \350\256\276\350\256\241\345\233\276.vsd" "b/docs/RocketMQ \350\256\276\350\256\241\345\233\276.vsd" deleted file mode 100644 index e6ff9d96..00000000 Binary files "a/docs/RocketMQ \350\256\276\350\256\241\345\233\276.vsd" and /dev/null differ diff --git a/docs/rocketmq.java.code.style.xml b/docs/rocketmq.java.code.style.xml new file mode 100644 index 00000000..c0ac866d --- /dev/null +++ b/docs/rocketmq.java.code.style.xml @@ -0,0 +1,432 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/eclipse.bat b/eclipse.bat index 0d824546..9b286a4c 100644 --- a/eclipse.bat +++ b/eclipse.bat @@ -1,3 +1 @@ -call mvn -U eclipse:eclipse - -@pause \ No newline at end of file +mvn -U eclipse:eclipse diff --git a/install.bat b/install.bat new file mode 100644 index 00000000..2c3b5057 --- /dev/null +++ b/install.bat @@ -0,0 +1,2 @@ +mvn -Dmaven.test.skip=true clean package install assembly:assembly -U + diff --git a/install.sh b/install.sh index 35b7ca7a..f849ae3d 100644 --- a/install.sh +++ b/install.sh @@ -1,10 +1,13 @@ git pull +git checkout master + rm -rf target rm -f devenv - -export JAVA_HOME=/opt/taobao/java +if [ -z "$JAVA_HOME" ]; then + JAVA_HOME=/opt/taobao/java +fi export PATH=/opt/taobao/mvn/bin:$JAVA_HOME/bin:$PATH mvn -Dmaven.test.skip=true clean package install assembly:assembly -U -ln -s target/alibaba-rocketmq-3.0.0-SNAPSHOT.dir/alibaba-rocketmq devenv +ln -s target/alibaba-rocketmq-3.0.7.dir/alibaba-rocketmq devenv diff --git a/open/githubpage/index.html b/open/githubpage/index.html index 19f70029..da166fb5 100644 --- a/open/githubpage/index.html +++ b/open/githubpage/index.html @@ -1,79 +1,99 @@ - + - - - -淘宝METAQ开源消息中间件 - - + + + + 淘宝METAQ开源消息中间件 + + -
- - - 到Github上关注 - 查看Metaq文档 - - 下载安装包 - 联系我们 - +
+ + + 到Github上关注 + 查看Metaq文档 + + 下载安装包 + 联系我们 +
-
+
-
- - - - - -
METAQ是一款完全的队列模型消息中间件,服务器使用Java语言编写,可在多种软硬件平台上部署。客户端支持Java、C++编程语言。单台服务器可支持1万以上个消息队列,通过扩容服务器,队列数几乎可任意横向扩展。每个队列都是持久化、长度无限(取决于磁盘空间大小)、并且可从队列任意位置开始消费。 -
-
METAQ在阿里巴巴各个子公司被广泛应用,每天转发250亿+条消息。主要应用于异步解耦,Mysql数据复制,收集日志等场景。下面是使用METAQ的各个公司或项目名,阿里以外的公司通过与开发者交流得知,如有误请告知我们。如果您正在使用METAQ,也请告知。
-
-
这些公司在使用Metaq
- diff --git a/open/taobao.org/index.html b/open/taobao.org/index.html index 0869f39b..4eb542fb 100644 --- a/open/taobao.org/index.html +++ b/open/taobao.org/index.html @@ -1,29 +1,32 @@ - + - - - -淘宝METAQ开源消息中间件 - - + - + diff --git a/pom.xml b/pom.xml index 72238daa..17b59c75 100644 --- a/pom.xml +++ b/pom.xml @@ -1,19 +1,29 @@ + + 4.0.0 2012 com.alibaba.rocketmq rocketmq-all - 3.0.0-SNAPSHOT + 3.0.8-SNAPSHOT pom rocketmq-all ${project.version} + https://github.com/alibaba/rocketmq rocketmq-client @@ -25,9 +35,55 @@ rocketmq-namesrv rocketmq-remoting rocketmq-example - rocketmq-console + rocketmq-qatest + + + vintagewang + https://github.com/vintagewang + vintage.wang@gmail.com + 8 + + + manhong + https://github.com/YangJodie + manhong.yqd@alibaba-inc.com + 8 + + + lansheng + https://github.com/allenzhu + lansheng.zj@alibaba-inc.com + 8 + + + + + + Apache License, Version 2.0 + http://www.apache.org/licenses/LICENSE-2.0 + + + + + git@github.com:alibaba/rocketmq.git + scm:git:git@github.com:alibaba/rocketmq.git + scm:git:git@github.com:alibaba/rocketmq.git + + + + UTF-8 + + true + true + true + + 1.6 + 1.6 + UTF-8 + + @@ -35,26 +91,13 @@ maven-compiler-plugin 2.3.2 - 1.6 - 1.6 - GBK + ${java_source_version} + ${java_target_version} + ${file_encoding} true true - - com.atlassian.maven.plugins - maven-clover2-plugin - - clover.license - true - - **/notjunit/*.java - - true - true - - org.apache.maven.plugins maven-eclipse-plugin @@ -70,20 +113,25 @@ 2.3 -Xms512m -Xmx1024m - always + once **/*Test.java - - - - - org.apache.maven.plugins - maven-site-plugin - - zh_CN - GBK - GBK + + com/alibaba/rocketmq/remoting/ExceptionTest.java + com/alibaba/rocketmq/remoting/SyncInvokeTest.java + com/alibaba/rocketmq/remoting/NettyIdleTest.java + com/alibaba/rocketmq/remoting/NettyConnectionTest.java + com/alibaba/rocketmq/common/filter/PolishExprTest.java + com/alibaba/rocketmq/common/protocol/MQProtosHelperTest.java + com/alibaba/rocketmq/client/consumer/loadbalance/AllocateMessageQueueAveragelyTest.java + com/alibaba/rocketmq/store/RecoverTest.java + com/alibaba/rocketmq/broker/api/SendMessageTest.java + com/alibaba/rocketmq/test/integration/*/*.java + com/alibaba/rocketmq/test/integration/BaseTest.java + com/alibaba/rocketmq/test/*/*.java + com/alibaba/rocketmq/test/BaseTest.java + @@ -97,12 +145,55 @@ + + + org.apache.maven.plugins + maven-javadoc-plugin + 2.7 + + + attach-javadocs + + jar + + + + + ${maven.jdoc.skip} + ${file_encoding} + ${file_encoding} + org.jboss.apiviz.APIviz + + org.jboss.apiviz + apiviz + 1.3.0.GA + + true + true + true + true + true + + + + org.apache.maven.plugins + maven-source-plugin + 2.1.2 + + + attach-sources + + jar + + + + src/main/resources - true + false @@ -146,39 +237,29 @@ ${project.groupId} - rocketmq-console + rocketmq-qatest ${project.version} junit junit - 4.4 + 4.11 test - ch.qos.logback - logback-classic - 1.0.11 - - - commons-cli - commons-cli - 1.2 - - - apache-httpclient - commons-httpclient - 3.1 + org.slf4j + slf4j-api + 1.7.5 - apache-codec - commons-codec - 1.2 + ch.qos.logback + logback-classic + 1.0.13 - io.netty - netty-all - 4.0.0.CR2 + ch.qos.logback + logback-core + 1.0.13 commons-io @@ -186,41 +267,25 @@ 2.4 - commons-logging - commons-logging - 1.1.1 - - - com.google.protobuf - protobuf-java - 2.4.1 - - - org.powermock - powermock-module-junit4 - 1.5 - test + commons-cli + commons-cli + 1.2 - org.powermock - powermock-api-easymock - 1.5 - test + commons-httpclient + commons-httpclient + 3.1 - org.easymock - easymock - 3.1 - test + io.netty + netty-all + 4.0.13.Final - org.eclipse.jetty - jetty-server - 8.1.9.v20130131 - jar - compile + com.alibaba + fastjson + 1.1.37 - - \ No newline at end of file + diff --git a/release.xml b/release.xml index f61f13d0..2b6e49ff 100644 --- a/release.xml +++ b/release.xml @@ -1,43 +1,43 @@ - alibaba-rocketmq - - dir - tar.gz - - - - - bin/* - conf/* - test/* - benchmark/* - webroot/*/*/* - - - + alibaba-rocketmq + + dir + tar.gz + + + + + bin/* + conf/* + conf/*/* + test/* + benchmark/* + LICENSE.txt + + + - - - - com.alibaba.rocketmq:rocketmq-broker - com.alibaba.rocketmq:rocketmq-tools - com.alibaba.rocketmq:rocketmq-client - com.alibaba.rocketmq:rocketmq-research - com.alibaba.rocketmq:rocketmq-namesrv - com.alibaba.rocketmq:rocketmq-console - com.alibaba.rocketmq:rocketmq-example - - - lib/ - false - - - lib/ - - - - - + + + + com.alibaba.rocketmq:rocketmq-broker + com.alibaba.rocketmq:rocketmq-tools + com.alibaba.rocketmq:rocketmq-client + com.alibaba.rocketmq:rocketmq-research + com.alibaba.rocketmq:rocketmq-namesrv + com.alibaba.rocketmq:rocketmq-example + + + lib/ + false + + + lib/ + + + + + diff --git a/rocketmq-broker/pom.xml b/rocketmq-broker/pom.xml index 30f77b2c..f40f4092 100644 --- a/rocketmq-broker/pom.xml +++ b/rocketmq-broker/pom.xml @@ -1,14 +1,12 @@ - + com.alibaba.rocketmq rocketmq-all - 3.0.0-SNAPSHOT + 3.0.8-SNAPSHOT 4.0.0 jar - com.alibaba.rocketmq rocketmq-broker rocketmq-broker ${project.version} @@ -18,10 +16,6 @@ junit test - - ch.qos.logback - logback-classic - ${project.groupId} rocketmq-common @@ -42,5 +36,17 @@ commons-cli commons-cli + + ch.qos.logback + logback-classic + + + ch.qos.logback + logback-core + + + com.alibaba + fastjson + diff --git a/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/BrokerController.java b/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/BrokerController.java index b9f07acd..5517c128 100644 --- a/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/BrokerController.java +++ b/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/BrokerController.java @@ -1,15 +1,29 @@ /** - * $Id: BrokerController.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.broker; import java.io.IOException; import java.util.Properties; -import java.util.Random; +import java.util.concurrent.BlockingQueue; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; +import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ThreadFactory; +import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; @@ -17,24 +31,37 @@ import org.slf4j.LoggerFactory; import com.alibaba.rocketmq.broker.client.ClientHousekeepingService; +import com.alibaba.rocketmq.broker.client.ConsumerIdsChangeListener; import com.alibaba.rocketmq.broker.client.ConsumerManager; +import com.alibaba.rocketmq.broker.client.DefaultConsumerIdsChangeListener; import com.alibaba.rocketmq.broker.client.ProducerManager; +import com.alibaba.rocketmq.broker.client.net.Broker2Client; +import com.alibaba.rocketmq.broker.client.rebalance.RebalanceLockManager; +import com.alibaba.rocketmq.broker.digestlog.DigestLogManager; import com.alibaba.rocketmq.broker.longpolling.PullRequestHoldService; import com.alibaba.rocketmq.broker.offset.ConsumerOffsetManager; +import com.alibaba.rocketmq.broker.out.BrokerOuterAPI; import com.alibaba.rocketmq.broker.processor.AdminBrokerProcessor; import com.alibaba.rocketmq.broker.processor.ClientManageProcessor; import com.alibaba.rocketmq.broker.processor.EndTransactionProcessor; import com.alibaba.rocketmq.broker.processor.PullMessageProcessor; import com.alibaba.rocketmq.broker.processor.QueryMessageProcessor; import com.alibaba.rocketmq.broker.processor.SendMessageProcessor; +import com.alibaba.rocketmq.broker.slave.SlaveSynchronize; +import com.alibaba.rocketmq.broker.stats.BrokerStats; +import com.alibaba.rocketmq.broker.subscription.SubscriptionGroupManager; import com.alibaba.rocketmq.broker.topic.TopicConfigManager; +import com.alibaba.rocketmq.broker.transaction.DefaultTransactionCheckExecuter; import com.alibaba.rocketmq.common.BrokerConfig; import com.alibaba.rocketmq.common.DataVersion; import com.alibaba.rocketmq.common.MixAll; -import com.alibaba.rocketmq.common.namesrv.TopAddressing; +import com.alibaba.rocketmq.common.UtilAll; +import com.alibaba.rocketmq.common.constant.LoggerName; +import com.alibaba.rocketmq.common.namesrv.RegisterBrokerResult; import com.alibaba.rocketmq.common.protocol.MQProtos; -import com.alibaba.rocketmq.common.protocol.MQProtosHelper; +import com.alibaba.rocketmq.common.protocol.body.TopicConfigSerializeWrapper; import com.alibaba.rocketmq.remoting.RemotingServer; +import com.alibaba.rocketmq.remoting.netty.NettyClientConfig; import com.alibaba.rocketmq.remoting.netty.NettyRemotingServer; import com.alibaba.rocketmq.remoting.netty.NettyRequestProcessor; import com.alibaba.rocketmq.remoting.netty.NettyServerConfig; @@ -45,126 +72,137 @@ /** - * Broker + * Broker各个服务控制器 * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * @author shijia.wxr + * @since 2013-7-26 */ public class BrokerController { - private static final Logger log = LoggerFactory.getLogger(MixAll.BrokerLoggerName); - // + private static final Logger log = LoggerFactory.getLogger(LoggerName.BrokerLoggerName); + // 服务器配置 private final BrokerConfig brokerConfig; - // ͨŲ + // 通信层配置 private final NettyServerConfig nettyServerConfig; - // 洢 + private final NettyClientConfig nettyClientConfig; + // 存储层配置 private final MessageStoreConfig messageStoreConfig; - // ļ汾 + // 配置文件版本号 private final DataVersion configDataVersion = new DataVersion(); - - // 洢 - private MessageStore messageStore; - // ͨŲ - private RemotingServer remotingServer; - - // ѽȴ洢 + // 消费进度存储 private final ConsumerOffsetManager consumerOffsetManager; - // ConsumerӡĹϵ + // Consumer连接、订阅关系管理 private final ConsumerManager consumerManager; - // Producerӹ + // Producer连接管理 private final ProducerManager producerManager; - // пͻ + // 检测所有客户端连接 private final ClientHousekeepingService clientHousekeepingService; - - // Topic - private TopicConfigManager topicConfigManager; - - // Ϣ̳߳ - private ExecutorService sendMessageExecutor; - // ȡϢ̳߳ - private ExecutorService pullMessageExecutor; - // Broker̳߳ - private ExecutorService adminBrokerExecutor; - + // Broker主动回查Producer事务状态 + private final DefaultTransactionCheckExecuter defaultTransactionCheckExecuter; private final PullMessageProcessor pullMessageProcessor; private final PullRequestHoldService pullRequestHoldService; - - private ScheduledExecutorService scheduledExecutorService = Executors + // Broker主动调用Client + private final Broker2Client broker2Client; + // 订阅组配置管理 + private final SubscriptionGroupManager subscriptionGroupManager; + // 订阅组内成员发生变化,立刻通知所有成员 + private final ConsumerIdsChangeListener consumerIdsChangeListener; + // 管理队列的锁分配 + private final RebalanceLockManager rebalanceLockManager = new RebalanceLockManager(); + // Broker的通信层客户端 + private final BrokerOuterAPI brokerOuterAPI; + private final ScheduledExecutorService scheduledExecutorService = Executors .newSingleThreadScheduledExecutor(new ThreadFactory() { @Override public Thread newThread(Runnable r) { return new Thread(r, "BrokerControllerScheduledThread"); } }); + // Slave定期从Master同步信息 + private final SlaveSynchronize slaveSynchronize; + private final DigestLogManager digestLogManager; + // 存储层对象 + private MessageStore messageStore; + // 通信层对象 + private RemotingServer remotingServer; + // Topic配置 + private TopicConfigManager topicConfigManager; + // 处理发送消息线程池 + private ExecutorService sendMessageExecutor; + // 处理拉取消息线程池 + private ExecutorService pullMessageExecutor; + // 处理管理Broker线程池 + private ExecutorService adminBrokerExecutor; + // 是否需要定期更新HA Master地址 + private boolean updateMasterHAServerAddrPeriodically = false; + + private BrokerStats brokerStats; + // 对消息写入进行流控 + private final BlockingQueue sendThreadPoolQueue; + // 对消息读取进行流控 + private final BlockingQueue pullThreadPoolQueue; - public BrokerController(final BrokerConfig brokerConfig, final NettyServerConfig nettyServerConfig, - final MessageStoreConfig messageStoreConfig) { + + public BrokerController(// + final BrokerConfig brokerConfig, // + final NettyServerConfig nettyServerConfig, // + final NettyClientConfig nettyClientConfig, // + final MessageStoreConfig messageStoreConfig // + ) { this.brokerConfig = brokerConfig; this.nettyServerConfig = nettyServerConfig; + this.nettyClientConfig = nettyClientConfig; this.messageStoreConfig = messageStoreConfig; this.consumerOffsetManager = new ConsumerOffsetManager(this); this.topicConfigManager = new TopicConfigManager(this); this.pullMessageProcessor = new PullMessageProcessor(this); this.pullRequestHoldService = new PullRequestHoldService(this); - this.consumerManager = new ConsumerManager(); + this.consumerIdsChangeListener = new DefaultConsumerIdsChangeListener(this); + this.consumerManager = new ConsumerManager(this.consumerIdsChangeListener); this.producerManager = new ProducerManager(); this.clientHousekeepingService = new ClientHousekeepingService(this); - } - - - public String getBrokerAddr() { - String addr = this.brokerConfig.getBrokerIP1() + ":" + this.nettyServerConfig.getListenPort(); - return addr; - } + this.defaultTransactionCheckExecuter = new DefaultTransactionCheckExecuter(this); + this.broker2Client = new Broker2Client(this); + this.subscriptionGroupManager = new SubscriptionGroupManager(this); + this.brokerOuterAPI = new BrokerOuterAPI(nettyClientConfig); + + if (this.brokerConfig.getNamesrvAddr() != null) { + this.brokerOuterAPI.updateNameServerAddressList(this.brokerConfig.getNamesrvAddr()); + log.info("user specfied name server address: {}", this.brokerConfig.getNamesrvAddr()); + } + this.slaveSynchronize = new SlaveSynchronize(this); + this.digestLogManager = new DigestLogManager(this); - private boolean registerToNameServer() { - TopAddressing topAddressing = new TopAddressing(); - String addrs = - (null == this.brokerConfig.getNamesrvAddr()) ? topAddressing.fetchNSAddr() : this.brokerConfig - .getNamesrvAddr(); - if (addrs != null) { - String[] addrArray = addrs.split(";"); - - if (addrArray != null && addrArray.length > 0) { - Random r = new Random(); - int begin = Math.abs(r.nextInt()) % 1000000; - for (int i = 0; i < addrArray.length; i++) { - String addr = addrArray[begin++ % addrArray.length]; - boolean result = - MQProtosHelper.registerBrokerToNameServer(addr, this.getBrokerAddr(), 1000 * 10); - log.info("register broker[" + this.getBrokerAddr() + "] to name server[" + addr + "] " - + (result ? " success" : " failed")); - if (result) - return true; - } - } - } + this.sendThreadPoolQueue = + new LinkedBlockingQueue(this.brokerConfig.getSendThreadPoolQueueCapacity()); - return false; + this.pullThreadPoolQueue = + new LinkedBlockingQueue(this.brokerConfig.getPullThreadPoolQueueCapacity()); } public boolean initialize() { boolean result = true; - // ӡò + // 打印服务器配置参数 MixAll.printObjectProperties(log, this.brokerConfig); MixAll.printObjectProperties(log, this.nettyServerConfig); MixAll.printObjectProperties(log, this.messageStoreConfig); - // עᵽName Server - // result = result && this.registerToNameServer(); - registerToNameServer(); - // Topic + // 加载Topic配置 result = result && this.topicConfigManager.load(); - // Consumer Offset + // 加载Consumer Offset result = result && this.consumerOffsetManager.load(); + // 加载Consumer subscription + result = result && this.subscriptionGroupManager.load(); - // ʼ洢 + // 初始化存储层 if (result) { try { - this.messageStore = new DefaultMessageStore(this.messageStoreConfig); + this.messageStore = + new DefaultMessageStore(this.messageStoreConfig, this.defaultTransactionCheckExecuter); } catch (IOException e) { result = false; @@ -172,39 +210,46 @@ public boolean initialize() { } } - // رϢ + // 加载本地消息数据 result = result && this.messageStore.load(); if (result) { - // ʼͨŲ - this.remotingServer = new NettyRemotingServer(this.nettyServerConfig, this.clientHousekeepingService); - - // ʼ̳߳ - this.sendMessageExecutor = - Executors.newFixedThreadPool(this.brokerConfig.getSendMessageThreadPoolNums(), - new ThreadFactory() { - - private AtomicInteger threadIndex = new AtomicInteger(0); - - - @Override - public Thread newThread(Runnable r) { - return new Thread(r, "SendMessageThread_" + this.threadIndex.incrementAndGet()); - } - }); - - this.pullMessageExecutor = - Executors.newFixedThreadPool(this.brokerConfig.getPullMessageThreadPoolNums(), - new ThreadFactory() { + // 初始化通信层 + this.remotingServer = + new NettyRemotingServer(this.nettyServerConfig, this.clientHousekeepingService); + + // 初始化线程池 + this.sendMessageExecutor = new ThreadPoolExecutor(// + this.brokerConfig.getSendMessageThreadPoolNums(),// + this.brokerConfig.getSendMessageThreadPoolNums(),// + 1000 * 60,// + TimeUnit.MILLISECONDS,// + this.sendThreadPoolQueue,// + new ThreadFactory() { + private AtomicInteger threadIndex = new AtomicInteger(0); + + + @Override + public Thread newThread(Runnable r) { + return new Thread(r, "SendMessageThread_" + this.threadIndex.incrementAndGet()); + } + }); - private AtomicInteger threadIndex = new AtomicInteger(0); + this.pullMessageExecutor = new ThreadPoolExecutor(// + this.brokerConfig.getPullMessageThreadPoolNums(),// + this.brokerConfig.getPullMessageThreadPoolNums(),// + 1000 * 60,// + TimeUnit.MILLISECONDS,// + this.pullThreadPoolQueue,// + new ThreadFactory() { + private AtomicInteger threadIndex = new AtomicInteger(0); - @Override - public Thread newThread(Runnable r) { - return new Thread(r, "PullMessageThread_" + this.threadIndex.incrementAndGet()); - } - }); + @Override + public Thread newThread(Runnable r) { + return new Thread(r, "PullMessageThread_" + this.threadIndex.incrementAndGet()); + } + }); this.adminBrokerExecutor = Executors.newFixedThreadPool(this.brokerConfig.getAdminBrokerThreadPoolNums(), @@ -215,49 +260,100 @@ public Thread newThread(Runnable r) { @Override public Thread newThread(Runnable r) { - return new Thread(r, "AdminBrokerThread_" + this.threadIndex.incrementAndGet()); + return new Thread(r, "AdminBrokerThread_" + + this.threadIndex.incrementAndGet()); } }); this.registerProcessor(); - // ʱˢѽ + this.brokerStats = new BrokerStats((DefaultMessageStore) this.messageStore); + + // 每天凌晨00:00:00统计消息量 + final long initialDelay = UtilAll.computNextMorningTimeMillis() - System.currentTimeMillis(); + final long period = 1000 * 60 * 60 * 24; this.scheduledExecutorService.scheduleAtFixedRate(new Runnable() { @Override public void run() { try { - BrokerController.this.consumerOffsetManager.flush(); + BrokerController.this.getBrokerStats().record(); } catch (Exception e) { log.error("", e); } } - }, 1000 * 10, this.brokerConfig.getFlushConsumerOffsetInterval(), TimeUnit.MILLISECONDS); + }, initialDelay, period, TimeUnit.MILLISECONDS); - // ʱˢѽȣʷ¼ɱ + // 定时刷消费进度 this.scheduledExecutorService.scheduleAtFixedRate(new Runnable() { @Override public void run() { try { - BrokerController.this.consumerOffsetManager.flushHistory(); + BrokerController.this.consumerOffsetManager.persist(); + } + catch (Exception e) { + log.error("", e); + } + } + }, 1000 * 10, this.brokerConfig.getFlushConsumerOffsetInterval(), TimeUnit.MILLISECONDS); + // 定时打印各个消费组的消费速度 + this.scheduledExecutorService.scheduleAtFixedRate(new Runnable() { + @Override + public void run() { + try { BrokerController.this.consumerOffsetManager.recordPullTPS(); } catch (Exception e) { - log.error("", e); + log.error("recordPullTPS Exception", e); } } }, 1000 * 10, this.brokerConfig.getFlushConsumerOffsetHistoryInterval(), TimeUnit.MILLISECONDS); - // slave + // 先获取Name Server地址 + if (this.brokerConfig.getNamesrvAddr() != null) { + this.brokerOuterAPI.updateNameServerAddressList(this.brokerConfig.getNamesrvAddr()); + } + // 定时获取Name Server地址 + else if (this.brokerConfig.isFetchNamesrvAddrByAddressServer()) { + this.scheduledExecutorService.scheduleAtFixedRate(new Runnable() { + + @Override + public void run() { + try { + BrokerController.this.brokerOuterAPI.fetchNameServerAddr(); + } + catch (Exception e) { + log.error("ScheduledTask fetchNameServerAddr exception", e); + } + } + }, 1000 * 10, 1000 * 60 * 2, TimeUnit.MILLISECONDS); + } + + // 如果是slave if (BrokerRole.SLAVE == this.messageStoreConfig.getBrokerRole()) { - if (this.messageStoreConfig.getMasterAddress() != null - && this.messageStoreConfig.getMasterAddress().length() >= 6) { - this.messageStore.updateMasterAddress(this.messageStoreConfig.getMasterAddress()); + if (this.messageStoreConfig.getHaMasterAddress() != null + && this.messageStoreConfig.getHaMasterAddress().length() >= 6) { + this.messageStore.updateHaMasterAddress(this.messageStoreConfig.getHaMasterAddress()); + this.updateMasterHAServerAddrPeriodically = false; } else { - // TODO ʱȥµַ + this.updateMasterHAServerAddrPeriodically = true; } + + // Slave定时从Master同步配置信息 + this.scheduledExecutorService.scheduleAtFixedRate(new Runnable() { + + @Override + public void run() { + try { + BrokerController.this.slaveSynchronize.syncAll(); + } + catch (Exception e) { + log.error("ScheduledTask syncAll slave exception", e); + } + } + }, 1000 * 10, 1000 * 60, TimeUnit.MILLISECONDS); } } @@ -266,47 +362,137 @@ public void run() { public void registerProcessor() { - this.remotingServer.registerProcessor(MQProtos.MQRequestCode.SEND_MESSAGE_VALUE, new SendMessageProcessor( - this), this.sendMessageExecutor); - + /** + * SendMessageProcessor + */ + NettyRequestProcessor sendProcessor = new SendMessageProcessor(this); + this.remotingServer.registerProcessor(MQProtos.MQRequestCode.SEND_MESSAGE_VALUE, sendProcessor, + this.sendMessageExecutor); + this.remotingServer.registerProcessor(MQProtos.MQRequestCode.CONSUMER_SEND_MSG_BACK_VALUE, + sendProcessor, this.sendMessageExecutor); + + /** + * PullMessageProcessor + */ this.remotingServer.registerProcessor(MQProtos.MQRequestCode.PULL_MESSAGE_VALUE, this.pullMessageProcessor, this.pullMessageExecutor); + /** + * QueryMessageProcessor + */ NettyRequestProcessor queryProcessor = new QueryMessageProcessor(this); this.remotingServer.registerProcessor(MQProtos.MQRequestCode.QUERY_MESSAGE_VALUE, queryProcessor, this.pullMessageExecutor); - this.remotingServer.registerProcessor(MQProtos.MQRequestCode.VIEW_MESSAGE_BY_ID_VALUE, queryProcessor, - this.pullMessageExecutor); + this.remotingServer.registerProcessor(MQProtos.MQRequestCode.VIEW_MESSAGE_BY_ID_VALUE, + queryProcessor, this.pullMessageExecutor); + /** + * ClientManageProcessor + */ NettyRequestProcessor clientProcessor = new ClientManageProcessor(this); this.remotingServer.registerProcessor(MQProtos.MQRequestCode.HEART_BEAT_VALUE, clientProcessor, this.adminBrokerExecutor); - this.remotingServer.registerProcessor(MQProtos.MQRequestCode.UNREGISTER_CLIENT_VALUE, queryProcessor, - this.adminBrokerExecutor); - + this.remotingServer.registerProcessor(MQProtos.MQRequestCode.UNREGISTER_CLIENT_VALUE, + clientProcessor, this.adminBrokerExecutor); + this.remotingServer.registerProcessor(MQProtos.MQRequestCode.GET_CONSUMER_LIST_BY_GROUP_VALUE, + clientProcessor, this.adminBrokerExecutor); + + /** + * EndTransactionProcessor + */ this.remotingServer.registerProcessor(MQProtos.MQRequestCode.END_TRANSACTION_VALUE, new EndTransactionProcessor(this), this.sendMessageExecutor); - this.remotingServer.registerDefaultProcessor(new AdminBrokerProcessor(this), this.adminBrokerExecutor); + /** + * Default + */ + this.remotingServer + .registerDefaultProcessor(new AdminBrokerProcessor(this), this.adminBrokerExecutor); } - public void start() throws Exception { - if (this.messageStore != null) { - this.messageStore.start(); - } + public Broker2Client getBroker2Client() { + return broker2Client; + } - if (this.remotingServer != null) { - this.remotingServer.start(); - } - if (this.pullRequestHoldService != null) { - this.pullRequestHoldService.start(); - } + public BrokerConfig getBrokerConfig() { + return brokerConfig; + } - if (this.clientHousekeepingService != null) { - this.clientHousekeepingService.start(); - } + + public String getConfigDataVersion() { + return this.configDataVersion.toJson(); + } + + + public ConsumerManager getConsumerManager() { + return consumerManager; + } + + + public ConsumerOffsetManager getConsumerOffsetManager() { + return consumerOffsetManager; + } + + + public DefaultTransactionCheckExecuter getDefaultTransactionCheckExecuter() { + return defaultTransactionCheckExecuter; + } + + + public MessageStore getMessageStore() { + return messageStore; + } + + + public void setMessageStore(MessageStore messageStore) { + this.messageStore = messageStore; + } + + + public MessageStoreConfig getMessageStoreConfig() { + return messageStoreConfig; + } + + + public NettyServerConfig getNettyServerConfig() { + return nettyServerConfig; + } + + + public ProducerManager getProducerManager() { + return producerManager; + } + + + public PullMessageProcessor getPullMessageProcessor() { + return pullMessageProcessor; + } + + + public PullRequestHoldService getPullRequestHoldService() { + return pullRequestHoldService; + } + + + public RemotingServer getRemotingServer() { + return remotingServer; + } + + + public void setRemotingServer(RemotingServer remotingServer) { + this.remotingServer = remotingServer; + } + + + public SubscriptionGroupManager getSubscriptionGroupManager() { + return subscriptionGroupManager; + } + + + public DigestLogManager getDigestLogManager() { + return digestLogManager; } @@ -328,6 +514,13 @@ public void shutdown() { } this.scheduledExecutorService.shutdown(); + try { + this.scheduledExecutorService.awaitTermination(5000, TimeUnit.MILLISECONDS); + } + catch (InterruptedException e) { + } + + this.unregisterBrokerAll(); if (this.sendMessageExecutor != null) { this.sendMessageExecutor.shutdown(); @@ -341,47 +534,90 @@ public void shutdown() { this.adminBrokerExecutor.shutdown(); } - this.consumerOffsetManager.flush(); + if (this.brokerOuterAPI != null) { + this.brokerOuterAPI.shutdown(); + } + this.digestLogManager.dispose(); + + this.consumerOffsetManager.persist(); } - public MessageStore getMessageStore() { - return messageStore; + private void unregisterBrokerAll() { + this.brokerOuterAPI.unregisterBrokerAll(// + this.brokerConfig.getBrokerClusterName(), // + this.getBrokerAddr(), // + this.brokerConfig.getBrokerName(), // + this.brokerConfig.getBrokerId()); } - public void setMessageStore(MessageStore messageStore) { - this.messageStore = messageStore; + public String getBrokerAddr() { + String addr = this.brokerConfig.getBrokerIP1() + ":" + this.nettyServerConfig.getListenPort(); + return addr; } - public RemotingServer getRemotingServer() { - return remotingServer; - } + public void start() throws Exception { + if (this.messageStore != null) { + this.messageStore.start(); + } + if (this.remotingServer != null) { + this.remotingServer.start(); + } - public void setRemotingServer(RemotingServer remotingServer) { - this.remotingServer = remotingServer; - } + if (this.brokerOuterAPI != null) { + this.brokerOuterAPI.start(); + } + if (this.pullRequestHoldService != null) { + this.pullRequestHoldService.start(); + } - public BrokerConfig getBrokerConfig() { - return brokerConfig; - } + if (this.clientHousekeepingService != null) { + this.clientHousekeepingService.start(); + } + // 启动统计日志 + this.digestLogManager.start(); + // 启动时,强制注册 + this.registerBrokerAll(); - public NettyServerConfig getNettyServerConfig() { - return nettyServerConfig; + // 定时注册Broker到Name Server + this.scheduledExecutorService.scheduleAtFixedRate(new Runnable() { + + @Override + public void run() { + try { + BrokerController.this.registerBrokerAll(); + } + catch (Exception e) { + log.error("registerBrokerAll Exception", e); + } + } + }, 1000 * 10, 1000 * 30, TimeUnit.MILLISECONDS); } - public MessageStoreConfig getMessageStoreConfig() { - return messageStoreConfig; - } + public synchronized void registerBrokerAll() { + TopicConfigSerializeWrapper topicConfigWrapper = + this.getTopicConfigManager().buildTopicConfigSerializeWrapper(); + RegisterBrokerResult registerBrokerResult = this.brokerOuterAPI.registerBrokerAll(// + this.brokerConfig.getBrokerClusterName(), // + this.getBrokerAddr(), // + this.brokerConfig.getBrokerName(), // + this.brokerConfig.getBrokerId(), // + this.getHAServerAddr(), topicConfigWrapper); - public ConsumerOffsetManager getConsumerOffsetManager() { - return consumerOffsetManager; + if (registerBrokerResult != null) { + if (this.updateMasterHAServerAddrPeriodically && registerBrokerResult.getHaServerAddr() != null) { + this.messageStore.updateHaMasterAddress(registerBrokerResult.getHaServerAddr()); + } + + this.slaveSynchronize.setMasterAddr(registerBrokerResult.getMasterAddr()); + } } @@ -395,9 +631,16 @@ public void setTopicConfigManager(TopicConfigManager topicConfigManager) { } + public String getHAServerAddr() { + String addr = this.brokerConfig.getBrokerIP2() + ":" + this.messageStoreConfig.getHaListenPort(); + return addr; + } + + public void updateAllConfig(Properties properties) { MixAll.properties2Object(properties, brokerConfig); MixAll.properties2Object(properties, nettyServerConfig); + MixAll.properties2Object(properties, nettyClientConfig); MixAll.properties2Object(properties, messageStoreConfig); this.configDataVersion.nextVersion(); this.flushAllConfig(); @@ -406,8 +649,13 @@ public void updateAllConfig(Properties properties) { private void flushAllConfig() { String allConfig = this.encodeAllConfig(); - boolean result = MixAll.string2File(allConfig, this.brokerConfig.getConfigFilePath()); - log.info("flush topic config, " + this.brokerConfig.getConfigFilePath() + (result ? " OK" : " Failed")); + try { + MixAll.string2File(allConfig, this.brokerConfig.getBrokerConfigPath()); + log.info("flush broker config, {} OK", this.brokerConfig.getBrokerConfigPath()); + } + catch (IOException e) { + log.info("flush broker config Exception, " + this.brokerConfig.getBrokerConfigPath(), e); + } } @@ -443,31 +691,56 @@ public String encodeAllConfig() { } } + { + Properties properties = MixAll.object2Properties(this.nettyClientConfig); + if (properties != null) { + sb.append(MixAll.properties2String(properties)); + } + else { + log.error("encodeAllConfig object2Properties error"); + } + } return sb.toString(); } - public String getConfigDataVersion() { - return this.configDataVersion.currentVersion(); + public RebalanceLockManager getRebalanceLockManager() { + return rebalanceLockManager; } - public PullMessageProcessor getPullMessageProcessor() { - return pullMessageProcessor; + public SlaveSynchronize getSlaveSynchronize() { + return slaveSynchronize; } - public PullRequestHoldService getPullRequestHoldService() { - return pullRequestHoldService; + public BrokerOuterAPI getBrokerOuterAPI() { + return brokerOuterAPI; } - public ConsumerManager getConsumerManager() { - return consumerManager; + public ExecutorService getPullMessageExecutor() { + return pullMessageExecutor; } - public ProducerManager getProducerManager() { - return producerManager; + public void setPullMessageExecutor(ExecutorService pullMessageExecutor) { + this.pullMessageExecutor = pullMessageExecutor; + } + + + public BrokerStats getBrokerStats() { + return brokerStats; } + + + public void setBrokerStats(BrokerStats brokerStats) { + this.brokerStats = brokerStats; + } + + + public BlockingQueue getSendThreadPoolQueue() { + return sendThreadPoolQueue; + } + } diff --git a/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/BrokerStartup.java b/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/BrokerStartup.java index fb3a1095..b34dcd03 100644 --- a/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/BrokerStartup.java +++ b/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/BrokerStartup.java @@ -1,5 +1,17 @@ /** - * $Id: BrokerStartup.java 1839 2013-05-16 02:12:02Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.broker; @@ -20,17 +32,21 @@ import ch.qos.logback.classic.joran.JoranConfigurator; import com.alibaba.rocketmq.common.BrokerConfig; -import com.alibaba.rocketmq.common.MixAll; import com.alibaba.rocketmq.common.MQVersion; +import com.alibaba.rocketmq.common.MixAll; +import com.alibaba.rocketmq.common.constant.LoggerName; +import com.alibaba.rocketmq.remoting.netty.NettyClientConfig; import com.alibaba.rocketmq.remoting.netty.NettyServerConfig; import com.alibaba.rocketmq.remoting.protocol.RemotingCommand; +import com.alibaba.rocketmq.store.config.BrokerRole; import com.alibaba.rocketmq.store.config.MessageStoreConfig; /** - * Broker + * Broker启动入口 * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * @author shijia.wxr + * @since 2013-7-26 */ public class BrokerStartup { @@ -39,7 +55,7 @@ public static Options buildCommandlineOptions(final Options options) { opt.setRequired(false); options.addOption(opt); - opt = new Option("t", "topicProperties", true, "Topic config properties file"); + opt = new Option("t", "topicConfig", true, "Topic config json file"); opt.setRequired(false); options.addOption(opt); @@ -47,39 +63,63 @@ public static Options buildCommandlineOptions(final Options options) { opt.setRequired(false); options.addOption(opt); + opt = new Option("m", "printImportantConfig", false, "Print important config item"); + opt.setRequired(false); + options.addOption(opt); + return options; } public static void main(String[] args) { - // õǰ汾ţÿη汾ʱҪ޸CurrentVersion + main0(args); + } + + + public static BrokerController main0(String[] args) { System.setProperty(RemotingCommand.RemotingVersionKey, Integer.toString(MQVersion.CurrentVersion)); try { - // + // 解析命令行 Options options = MixAll.buildCommandlineOptions(new Options()); final CommandLine commandLine = - MixAll.parseCmdLine("mqbroker", args, buildCommandlineOptions(options), new PosixParser()); + MixAll + .parseCmdLine("mqbroker", args, buildCommandlineOptions(options), new PosixParser()); if (null == commandLine) { System.exit(-1); - return; + return null; } - // ʼļ + // 初始化配置文件 final BrokerConfig brokerConfig = new BrokerConfig(); final NettyServerConfig nettyServerConfig = new NettyServerConfig(); + final NettyClientConfig nettyClientConfig = new NettyClientConfig(); nettyServerConfig.setListenPort(10911); final MessageStoreConfig messageStoreConfig = new MessageStoreConfig(); - // ӡĬ + // 如果是slave,修改默认值 + if (BrokerRole.SLAVE == messageStoreConfig.getBrokerRole()) { + int ratio = messageStoreConfig.getAccessMessageInMemoryMaxRatio() - 10; + messageStoreConfig.setAccessMessageInMemoryMaxRatio(ratio); + } + + // 打印默认配置 if (commandLine.hasOption('p')) { MixAll.printObjectProperties(null, brokerConfig); MixAll.printObjectProperties(null, nettyServerConfig); + MixAll.printObjectProperties(null, nettyClientConfig); MixAll.printObjectProperties(null, messageStoreConfig); System.exit(0); } + else if (commandLine.hasOption('m')) { + MixAll.printObjectProperties(null, brokerConfig, true); + MixAll.printObjectProperties(null, nettyServerConfig, true); + MixAll.printObjectProperties(null, nettyClientConfig, true); + MixAll.printObjectProperties(null, messageStoreConfig, true); + System.exit(0); + } - // ָļ + // 指定配置文件 if (commandLine.hasOption('c')) { String file = commandLine.getOptionValue('c'); if (file != null) { @@ -88,15 +128,16 @@ public static void main(String[] args) { properties.load(in); MixAll.properties2Object(properties, brokerConfig); MixAll.properties2Object(properties, nettyServerConfig); + MixAll.properties2Object(properties, nettyClientConfig); MixAll.properties2Object(properties, messageStoreConfig); - brokerConfig.setConfigFilePath(file); + brokerConfig.setBrokerConfigPath(file); System.out.println("load config properties file OK, " + file); } } - // ָTopic + // 指定Topic配置项 if (commandLine.hasOption('t')) { String file = commandLine.getOptionValue('t'); if (file != null) { @@ -112,41 +153,47 @@ public static void main(String[] args) { System.exit(-2); } - // BrokerIdĴ + // BrokerId的处理 switch (messageStoreConfig.getBrokerRole()) { case ASYNC_MASTER: case SYNC_MASTER: - // Master Id0 + // Master Id必须是0 brokerConfig.setBrokerId(MixAll.MASTER_ID); break; case SLAVE: - // Slave IdSlaveIP˿ھ - long id = MixAll.createBrokerId(brokerConfig.getBrokerIP1(), nettyServerConfig.getListenPort()); - brokerConfig.setBrokerId(id); + if (brokerConfig.getBrokerId() <= 0) { + System.out.println("Slave's brokerId must be > 0"); + System.exit(-3); + } + break; default: break; } - // MasterSlaveĶ˿ڣĬΪ˿+1 + // Master监听Slave请求的端口,默认为服务端口+1 messageStoreConfig.setHaListenPort(nettyServerConfig.getListenPort() + 1); - // ʼLogback + // 初始化Logback LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory(); JoranConfigurator configurator = new JoranConfigurator(); configurator.setContext(lc); lc.reset(); - configurator.doConfigure(brokerConfig.getRocketmqHome() + "/conf/log4j_broker.xml"); - final Logger log = LoggerFactory.getLogger(MixAll.BrokerLoggerName); + configurator.doConfigure(brokerConfig.getRocketmqHome() + "/conf/logback_broker.xml"); + final Logger log = LoggerFactory.getLogger(LoggerName.BrokerLoggerName); - // ӡ + // 打印启动参数 MixAll.printObjectProperties(log, brokerConfig); MixAll.printObjectProperties(log, nettyServerConfig); + MixAll.printObjectProperties(log, nettyClientConfig); MixAll.printObjectProperties(log, messageStoreConfig); - // ʼƶ - final BrokerController controller = - new BrokerController(brokerConfig, nettyServerConfig, messageStoreConfig); + // 初始化服务控制对象 + final BrokerController controller = new BrokerController(// + brokerConfig, // + nettyServerConfig, // + nettyClientConfig, // + messageStoreConfig); boolean initResult = controller.initialize(); if (!initResult) { controller.shutdown(); @@ -173,17 +220,21 @@ public void run() { } }, "ShutdownHook")); - // ƶ + // 启动服务控制对象 controller.start(); String tip = "The broker[" + controller.getBrokerConfig().getBrokerName() + ", " + controller.getBrokerAddr() + "] boot success."; log.info(tip); System.out.println(tip); + + return controller; } catch (Throwable e) { e.printStackTrace(); System.exit(-1); } + + return null; } } diff --git a/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/client/ClientChannelInfo.java b/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/client/ClientChannelInfo.java index 5f8b8a4c..55811f65 100644 --- a/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/client/ClientChannelInfo.java +++ b/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/client/ClientChannelInfo.java @@ -1,16 +1,28 @@ /** - * $Id: ClientChannelInfo.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.broker.client; -import com.alibaba.rocketmq.remoting.protocol.RemotingProtos.LanguageCode; - import io.netty.channel.Channel; +import com.alibaba.rocketmq.remoting.protocol.LanguageCode; + /** - * @author vintage.wang@gmail.com shijia.wxr@taobao.com - * + * @author shijia.wxr + * @since 2013-7-26 */ public class ClientChannelInfo { private final Channel channel; @@ -89,8 +101,9 @@ public boolean equals(Object obj) { if (other.channel != null) return false; } - else if (this.channel.id().intValue() != other.channel.id().intValue()) + else if (this.channel != other.channel) { return false; + } return true; } diff --git a/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/client/ClientHousekeepingService.java b/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/client/ClientHousekeepingService.java index d19419eb..0a5c9a5a 100644 --- a/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/client/ClientHousekeepingService.java +++ b/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/client/ClientHousekeepingService.java @@ -1,5 +1,17 @@ /** - * $Id$ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.broker.client; @@ -14,17 +26,18 @@ import org.slf4j.LoggerFactory; import com.alibaba.rocketmq.broker.BrokerController; -import com.alibaba.rocketmq.common.MixAll; +import com.alibaba.rocketmq.common.constant.LoggerName; import com.alibaba.rocketmq.remoting.ChannelEventListener; /** - * ڼͻӣ + * 定期检测客户端连接,清除不活动的连接 * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * @author shijia.wxr + * @since 2013-7-26 */ public class ClientHousekeepingService implements ChannelEventListener { - private static final Logger log = LoggerFactory.getLogger(MixAll.BrokerLoggerName); + private static final Logger log = LoggerFactory.getLogger(LoggerName.BrokerLoggerName); private final BrokerController brokerController; private ScheduledExecutorService scheduledExecutorService = Executors @@ -42,7 +55,7 @@ public ClientHousekeepingService(final BrokerController brokerController) { public void start() { - // ʱˢѽ + // 定时刷消费进度 this.scheduledExecutorService.scheduleAtFixedRate(new Runnable() { @Override public void run() { @@ -59,6 +72,7 @@ public void run() { private void scanExceptionChannel() { this.brokerController.getProducerManager().scanNotActiveChannel(); + this.brokerController.getConsumerManager().scanNotActiveChannel(); } @@ -85,4 +99,11 @@ public void onChannelException(String remoteAddr, Channel channel) { this.brokerController.getProducerManager().doChannelCloseEvent(remoteAddr, channel); this.brokerController.getConsumerManager().doChannelCloseEvent(remoteAddr, channel); } + + + @Override + public void onChannelIdle(String remoteAddr, Channel channel) { + this.brokerController.getProducerManager().doChannelCloseEvent(remoteAddr, channel); + this.brokerController.getConsumerManager().doChannelCloseEvent(remoteAddr, channel); + } } diff --git a/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/client/ConsumerGroupInfo.java b/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/client/ConsumerGroupInfo.java index c0a590ca..168578de 100644 --- a/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/client/ConsumerGroupInfo.java +++ b/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/client/ConsumerGroupInfo.java @@ -1,51 +1,103 @@ /** - * $Id: ConsumerGroupInfo.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.broker.client; import io.netty.channel.Channel; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Map.Entry; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.alibaba.rocketmq.common.MixAll; +import com.alibaba.rocketmq.common.constant.LoggerName; +import com.alibaba.rocketmq.common.consumer.ConsumeFromWhere; import com.alibaba.rocketmq.common.protocol.heartbeat.ConsumeType; import com.alibaba.rocketmq.common.protocol.heartbeat.MessageModel; import com.alibaba.rocketmq.common.protocol.heartbeat.SubscriptionData; /** - * Consumer GroupϢ - * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * 整个Consumer Group信息 * + * @author shijia.wxr + * @since 2013-7-26 */ public class ConsumerGroupInfo { - private static final Logger log = LoggerFactory.getLogger(MixAll.BrokerLoggerName); - + private static final Logger log = LoggerFactory.getLogger(LoggerName.BrokerLoggerName); private final String groupName; - private volatile ConsumeType consumeType; - private volatile MessageModel messageModel; private final ConcurrentHashMap subscriptionTable = new ConcurrentHashMap(); - private final ConcurrentHashMap channelInfoTable = - new ConcurrentHashMap(16); - + private final ConcurrentHashMap channelInfoTable = + new ConcurrentHashMap(16); + private volatile ConsumeType consumeType; + private volatile MessageModel messageModel; + private volatile ConsumeFromWhere consumeFromWhere; private volatile long lastUpdateTimestamp = System.currentTimeMillis(); - public ConsumerGroupInfo(String groupName, ConsumeType consumeType, MessageModel messageModel) { + public ConsumerGroupInfo(String groupName, ConsumeType consumeType, MessageModel messageModel, + ConsumeFromWhere consumeFromWhere) { this.groupName = groupName; this.consumeType = consumeType; this.messageModel = messageModel; + this.consumeFromWhere = consumeFromWhere; + } + + + public ConcurrentHashMap getSubscriptionTable() { + return subscriptionTable; + } + + + public ConcurrentHashMap getChannelInfoTable() { + return channelInfoTable; + } + + + public List getAllChannel() { + List result = new ArrayList(); + + result.addAll(this.channelInfoTable.keySet()); + + return result; + } + + + public List getAllClientId() { + List result = new ArrayList(); + + Iterator> it = this.channelInfoTable.entrySet().iterator(); + + while (it.hasNext()) { + Entry entry = it.next(); + ClientChannelInfo clientChannelInfo = entry.getValue(); + result.add(clientChannelInfo.getClientId()); + } + + return result; } public void unregisterChannel(final ClientChannelInfo clientChannelInfo) { - ClientChannelInfo old = this.channelInfoTable.remove(clientChannelInfo.getChannel().id()); + ClientChannelInfo old = this.channelInfoTable.remove(clientChannelInfo.getChannel()); if (old != null) { log.info("unregister a consumer[{}] from consumerGroupInfo {}", this.groupName, old.toString()); } @@ -53,7 +105,7 @@ public void unregisterChannel(final ClientChannelInfo clientChannelInfo) { public void doChannelCloseEvent(final String remoteAddr, final Channel channel) { - final ClientChannelInfo info = this.channelInfoTable.remove(channel.id()); + final ClientChannelInfo info = this.channelInfoTable.remove(channel); if (info != null) { log.warn( "NETTY EVENT: remove not active channel[{}] from ConsumerGroupInfo groupChannelTable, consumer group: {}", @@ -63,49 +115,89 @@ public void doChannelCloseEvent(final String remoteAddr, final Channel channel) /** - * ֵʾǷ + * 返回值表示是否发生变更 */ public boolean updateChannel(final ClientChannelInfo clientChannelInfo, ConsumeType consumeType, - MessageModel messageModel) { + MessageModel messageModel, ConsumeFromWhere consumeFromWhere) { boolean updated = false; this.consumeType = consumeType; this.messageModel = messageModel; - ClientChannelInfo info = this.channelInfoTable.get(clientChannelInfo.getChannel().id()); - if (info != null) { + this.consumeFromWhere = consumeFromWhere; + + ClientChannelInfo info = this.channelInfoTable.get(clientChannelInfo.getChannel()); + if (null == info) { ClientChannelInfo prev = - this.channelInfoTable.put(clientChannelInfo.getChannel().id(), clientChannelInfo); + this.channelInfoTable.put(clientChannelInfo.getChannel(), clientChannelInfo); if (null == prev) { log.info("new consumer connected, group: {} {} {} channel: {}", this.groupName, consumeType, messageModel, clientChannelInfo.toString()); updated = true; } + + info = clientChannelInfo; } this.lastUpdateTimestamp = System.currentTimeMillis(); + info.setLastUpdateTimestamp(this.lastUpdateTimestamp); + return updated; } /** - * ֵʾǷ + * 返回值表示是否发生变更 */ public boolean updateSubscription(final Set subList) { boolean updated = false; + // 增加新的订阅关系 for (SubscriptionData sub : subList) { SubscriptionData old = this.subscriptionTable.get(sub.getTopic()); if (old == null) { SubscriptionData prev = this.subscriptionTable.put(sub.getTopic(), sub); if (null == prev) { updated = true; + log.info("subscription changed, add new topic, group: {} {}", this.groupName, + sub.toString()); } } - else if (!sub.equals(old)) { + else if (sub.getSubVersion() > old.getSubVersion()) { + if (this.consumeType == ConsumeType.CONSUME_PASSIVELY) { + log.info("subscription changed, group: {} OLD: {} NEW: {}", // + this.groupName,// + old.toString(),// + sub.toString()// + ); + } + this.subscriptionTable.put(sub.getTopic(), sub); } } - // TODO ǷҪɾĶĹϵɾƺҲûɶӰ - // ȷʵtopicȡˣ Ӧ÷true + // 删除老的订阅关系 + Iterator> it = this.subscriptionTable.entrySet().iterator(); + while (it.hasNext()) { + Entry next = it.next(); + String oldTopic = next.getKey(); + + boolean exist = false; + for (SubscriptionData sub : subList) { + if (sub.getTopic().equals(oldTopic)) { + exist = true; + break; + } + } + + if (!exist) { + log.warn("subscription changed, group[{}] remove topic[{} {}], subList[{}]", // + this.groupName,// + oldTopic,// + next.getValue().toString(),// + subList); + + it.remove(); + updated = true; + } + } this.lastUpdateTimestamp = System.currentTimeMillis(); @@ -113,6 +205,11 @@ else if (!sub.equals(old)) { } + public SubscriptionData findSubscriptionData(final String topic) { + return this.subscriptionTable.get(topic); + } + + public ConsumeType getConsumeType() { return consumeType; } @@ -146,4 +243,14 @@ public long getLastUpdateTimestamp() { public void setLastUpdateTimestamp(long lastUpdateTimestamp) { this.lastUpdateTimestamp = lastUpdateTimestamp; } + + + public ConsumeFromWhere getConsumeFromWhere() { + return consumeFromWhere; + } + + + public void setConsumeFromWhere(ConsumeFromWhere consumeFromWhere) { + this.consumeFromWhere = consumeFromWhere; + } } diff --git a/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/client/ConsumerIdsChangeListener.java b/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/client/ConsumerIdsChangeListener.java new file mode 100644 index 00000000..65a2935a --- /dev/null +++ b/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/client/ConsumerIdsChangeListener.java @@ -0,0 +1,29 @@ +/** + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.rocketmq.broker.client; + +import io.netty.channel.Channel; + +import java.util.List; + + +/** + * @author shijia.wxr + * @since 2013-6-24 + */ +public interface ConsumerIdsChangeListener { + public void consumerIdsChanged(final String group, final List channels); +} diff --git a/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/client/ConsumerManager.java b/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/client/ConsumerManager.java index 9b3b04f3..d70d87d8 100644 --- a/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/client/ConsumerManager.java +++ b/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/client/ConsumerManager.java @@ -1,58 +1,106 @@ /** - * $Id: ConsumerManager.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.broker.client; import io.netty.channel.Channel; +import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.alibaba.rocketmq.common.constant.LoggerName; +import com.alibaba.rocketmq.common.consumer.ConsumeFromWhere; import com.alibaba.rocketmq.common.protocol.heartbeat.ConsumeType; import com.alibaba.rocketmq.common.protocol.heartbeat.MessageModel; import com.alibaba.rocketmq.common.protocol.heartbeat.SubscriptionData; +import com.alibaba.rocketmq.remoting.common.RemotingHelper; +import com.alibaba.rocketmq.remoting.common.RemotingUtil; /** - * ConsumerӡĹϵ - * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * Consumer连接、订阅关系管理 * + * @author shijia.wxr + * @since 2013-7-26 */ public class ConsumerManager { + private static final Logger log = LoggerFactory.getLogger(LoggerName.BrokerLoggerName); private final ConcurrentHashMap consumerTable = new ConcurrentHashMap(1024); + private final ConsumerIdsChangeListener consumerIdsChangeListener; + private static final long ChannelExpiredTimeout = 1000 * 120; + + + public ConsumerManager(final ConsumerIdsChangeListener consumerIdsChangeListener) { + this.consumerIdsChangeListener = consumerIdsChangeListener; + } + public ConsumerGroupInfo getConsumerGroupInfo(final String group) { return this.consumerTable.get(group); } + public SubscriptionData findSubscriptionData(final String group, final String topic) { + ConsumerGroupInfo consumerGroupInfo = this.getConsumerGroupInfo(group); + if (consumerGroupInfo != null) { + return consumerGroupInfo.findSubscriptionData(topic); + } + + return null; + } + + public void doChannelCloseEvent(final String remoteAddr, final Channel channel) { for (String group : this.consumerTable.keySet()) { final ConsumerGroupInfo info = this.consumerTable.get(group); if (info != null) { info.doChannelCloseEvent(remoteAddr, channel); + this.consumerIdsChangeListener.consumerIdsChanged(group, info.getAllChannel()); } } } /** - * Ƿб仯 + * 返回是否有变化 */ public boolean registerConsumer(final String group, final ClientChannelInfo clientChannelInfo, - ConsumeType consumeType, MessageModel messageModel, final Set subList) { + ConsumeType consumeType, MessageModel messageModel, ConsumeFromWhere consumeFromWhere, + final Set subList) { ConsumerGroupInfo consumerGroupInfo = this.consumerTable.get(group); if (null == consumerGroupInfo) { - ConsumerGroupInfo tmp = new ConsumerGroupInfo(group, consumeType, messageModel); + ConsumerGroupInfo tmp = new ConsumerGroupInfo(group, consumeType, messageModel, consumeFromWhere); ConsumerGroupInfo prev = this.consumerTable.putIfAbsent(group, tmp); consumerGroupInfo = prev != null ? prev : tmp; } - boolean r1 = consumerGroupInfo.updateChannel(clientChannelInfo, consumeType, messageModel); + boolean r1 = + consumerGroupInfo.updateChannel(clientChannelInfo, consumeType, messageModel, + consumeFromWhere); boolean r2 = consumerGroupInfo.updateSubscription(subList); + + if (r1 || r2) { + this.consumerIdsChangeListener.consumerIdsChanged(group, consumerGroupInfo.getAllChannel()); + } + return r1 || r2; } @@ -61,6 +109,29 @@ public void unregisterConsumer(final String group, final ClientChannelInfo clien ConsumerGroupInfo consumerGroupInfo = this.consumerTable.get(group); if (null != consumerGroupInfo) { consumerGroupInfo.unregisterChannel(clientChannelInfo); + this.consumerIdsChangeListener.consumerIdsChanged(group, consumerGroupInfo.getAllChannel()); + } + } + + + public void scanNotActiveChannel() { + for (String group : this.consumerTable.keySet()) { + final ConsumerGroupInfo info = this.consumerTable.get(group); + if (info != null) { + ConcurrentHashMap cloneChannels = + new ConcurrentHashMap(info.getChannelInfoTable()); + for (Map.Entry entry : cloneChannels.entrySet()) { + ClientChannelInfo clientChannelInfo = entry.getValue(); + long diff = System.currentTimeMillis() - clientChannelInfo.getLastUpdateTimestamp(); + if (diff > ChannelExpiredTimeout) { + log.warn( + "SCAN: remove expired channel from ConsumerManager consumerTable. channel={}, consumerGroup={}", + RemotingHelper.parseChannelRemoteAddr(entry.getKey()), group); + RemotingUtil.closeChannel(clientChannelInfo.getChannel()); + info.getChannelInfoTable().remove(entry.getKey()); + } + } + } } } } diff --git a/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/client/DefaultConsumerIdsChangeListener.java b/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/client/DefaultConsumerIdsChangeListener.java new file mode 100644 index 00000000..0caa3c5d --- /dev/null +++ b/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/client/DefaultConsumerIdsChangeListener.java @@ -0,0 +1,48 @@ +/** + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.rocketmq.broker.client; + +import io.netty.channel.Channel; + +import java.util.List; + +import com.alibaba.rocketmq.broker.BrokerController; + + +/** + * ConsumerId列表变化,通知所有Consumer + * + * @author shijia.wxr + * @since 2013-7-26 + */ +public class DefaultConsumerIdsChangeListener implements ConsumerIdsChangeListener { + private final BrokerController brokerController; + + + public DefaultConsumerIdsChangeListener(BrokerController brokerController) { + this.brokerController = brokerController; + } + + + @Override + public void consumerIdsChanged(String group, List channels) { + if (channels != null) { + for (Channel chl : channels) { + this.brokerController.getBroker2Client().notifyConsumerIdsChanged(chl, group); + } + } + } +} diff --git a/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/client/ProducerManager.java b/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/client/ProducerManager.java index 6cb17749..6a300b9e 100644 --- a/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/client/ProducerManager.java +++ b/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/client/ProducerManager.java @@ -1,5 +1,17 @@ /** - * $Id$ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.broker.client; @@ -7,8 +19,11 @@ import java.util.ArrayList; import java.util.HashMap; +import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.Map.Entry; +import java.util.Random; import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; @@ -16,32 +31,75 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.alibaba.rocketmq.common.MixAll; +import com.alibaba.rocketmq.common.constant.LoggerName; import com.alibaba.rocketmq.remoting.common.RemotingHelper; +import com.alibaba.rocketmq.remoting.common.RemotingUtil; /** - * Producer鼰Producer + * 管理Producer组及各个Producer连接 * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * @author shijia.wxr + * @since 2013-7-26 */ public class ProducerManager { - private static final Logger log = LoggerFactory.getLogger(MixAll.BrokerLoggerName); + private static final Logger log = LoggerFactory.getLogger(LoggerName.BrokerLoggerName); private static final long LockTimeoutMillis = 3000; - private static final long ChannelExpiredTimeout = 1000 * 120; - + private final Random random = new Random(System.currentTimeMillis()); private final Lock hashcodeChannelLock = new ReentrantLock(); private final HashMap> hashcodeChannelTable = new HashMap>(); - private final Lock groupChannelLock = new ReentrantLock(); - private final HashMap> groupChannelTable = - new HashMap>(); + private final HashMap> groupChannelTable = + new HashMap>(); public ProducerManager() { + } + + public HashMap> getGroupChannelTable() { + return groupChannelTable; + } + + + public ClientChannelInfo pickProducerChannelRandomly(final int producerGroupHashCode) { + try { + if (this.hashcodeChannelLock.tryLock(LockTimeoutMillis, TimeUnit.MILLISECONDS)) { + try { + List channelInfoList = + this.hashcodeChannelTable.get(producerGroupHashCode); + if (channelInfoList != null && !channelInfoList.isEmpty()) { + int index = this.generateRandmonNum() % channelInfoList.size(); + ClientChannelInfo info = channelInfoList.get(index); + return info; + } + } + finally { + this.hashcodeChannelLock.unlock(); + } + } + else { + log.warn("ProducerManager pickProducerChannelRandomly lock timeout"); + } + } + catch (InterruptedException e) { + log.error("", e); + } + + return null; + } + + + private int generateRandmonNum() { + int value = this.random.nextInt(); + + if (value < 0) { + value = Math.abs(value); + } + + return value; } @@ -49,26 +107,27 @@ public void scanNotActiveChannel() { try { if (this.hashcodeChannelLock.tryLock(LockTimeoutMillis, TimeUnit.MILLISECONDS)) { try { - for (final Map.Entry> entry : this.hashcodeChannelTable - .entrySet()) { + Iterator>> it = + this.hashcodeChannelTable.entrySet().iterator(); + + while (it.hasNext()) { + Entry> entry = it.next(); + final Integer groupHashCode = entry.getKey(); final List clientChannelInfoList = entry.getValue(); - final List willRemoveChannel = new ArrayList(); - for (ClientChannelInfo clientChannelInfo : clientChannelInfoList) { - long diff = System.currentTimeMillis() - clientChannelInfo.getLastUpdateTimestamp(); - if (diff > ChannelExpiredTimeout) { - willRemoveChannel.add(clientChannelInfo); - } - } - for (ClientChannelInfo clientChannelInfo : willRemoveChannel) { - boolean result = clientChannelInfoList.remove(clientChannelInfo); - if (result) { + Iterator itChannelInfo = clientChannelInfoList.iterator(); + while (itChannelInfo.hasNext()) { + ClientChannelInfo clientChannelInfo = itChannelInfo.next(); + long diff = + System.currentTimeMillis() - clientChannelInfo.getLastUpdateTimestamp(); + if (diff > ChannelExpiredTimeout) { log.warn( "SCAN: remove expired channel[{}] from ProducerManager hashcodeChannelTable, producer group hash code: {}", RemotingHelper.parseChannelRemoteAddr(clientChannelInfo.getChannel()), groupHashCode); - clientChannelInfo.getChannel().close(); + RemotingUtil.closeChannel(clientChannelInfo.getChannel()); + itChannelInfo.remove(); } } } @@ -78,7 +137,7 @@ public void scanNotActiveChannel() { } } else { - log.warn("ProducerManager closeChannel lock timeout"); + log.warn("ProducerManager scanNotActiveChannel lock timeout"); } } catch (InterruptedException e) { @@ -88,24 +147,24 @@ public void scanNotActiveChannel() { try { if (this.groupChannelLock.tryLock(LockTimeoutMillis, TimeUnit.MILLISECONDS)) { try { - for (final Map.Entry> entry : this.groupChannelTable + for (final Map.Entry> entry : this.groupChannelTable .entrySet()) { final String group = entry.getKey(); - final HashMap chlMap = entry.getValue(); + final HashMap chlMap = entry.getValue(); - for (final Map.Entry item : chlMap.entrySet()) { - final Integer id = item.getKey(); + Iterator> it = chlMap.entrySet().iterator(); + while (it.hasNext()) { + Entry item = it.next(); + // final Integer id = item.getKey(); final ClientChannelInfo info = item.getValue(); long diff = System.currentTimeMillis() - info.getLastUpdateTimestamp(); if (diff > ChannelExpiredTimeout) { - ClientChannelInfo old = chlMap.remove(id); - if (old != null) { - log.warn( - "SCAN: remove expired channel[{}] from ProducerManager groupChannelTable, producer group name: {}", - RemotingHelper.parseChannelRemoteAddr(info.getChannel()), group); - info.getChannel().close(); - } + it.remove(); + log.warn( + "SCAN: remove expired channel[{}] from ProducerManager groupChannelTable, producer group name: {}", + RemotingHelper.parseChannelRemoteAddr(info.getChannel()), group); + RemotingUtil.closeChannel(info.getChannel()); } } } @@ -115,7 +174,7 @@ public void scanNotActiveChannel() { } } else { - log.warn("ProducerManager closeChannel lock timeout"); + log.warn("ProducerManager scanNotActiveChannel lock timeout"); } } catch (InterruptedException e) { @@ -146,7 +205,7 @@ public void doChannelCloseEvent(final String remoteAddr, final Channel channel) } } else { - log.warn("ProducerManager closeChannel lock timeout"); + log.warn("ProducerManager doChannelCloseEvent lock timeout"); } } catch (InterruptedException e) { @@ -156,12 +215,13 @@ public void doChannelCloseEvent(final String remoteAddr, final Channel channel) try { if (this.groupChannelLock.tryLock(LockTimeoutMillis, TimeUnit.MILLISECONDS)) { try { - for (final Map.Entry> entry : this.groupChannelTable + for (final Map.Entry> entry : this.groupChannelTable .entrySet()) { final String group = entry.getKey(); - final HashMap clientChannelInfoTable = entry.getValue(); + final HashMap clientChannelInfoTable = + entry.getValue(); final ClientChannelInfo clientChannelInfo = - clientChannelInfoTable.remove(channel.id()); + clientChannelInfoTable.remove(channel); if (clientChannelInfo != null) { log.info( "NETTY EVENT: remove channel[{}][{}] from ProducerManager groupChannelTable, producer group: {}", @@ -174,7 +234,7 @@ public void doChannelCloseEvent(final String remoteAddr, final Channel channel) } } else { - log.warn("ProducerManager closeChannel lock timeout"); + log.warn("ProducerManager doChannelCloseEvent lock timeout"); } } catch (InterruptedException e) { @@ -226,15 +286,15 @@ public void registerProducer(final String group, final ClientChannelInfo clientC if (this.groupChannelLock.tryLock(LockTimeoutMillis, TimeUnit.MILLISECONDS)) { try { - HashMap channelTable = this.groupChannelTable.get(group); + HashMap channelTable = this.groupChannelTable.get(group); if (null == channelTable) { - channelTable = new HashMap(); + channelTable = new HashMap(); this.groupChannelTable.put(group, channelTable); } - clientChannelInfoFound = channelTable.get(clientChannelInfo.getChannel().id()); + clientChannelInfoFound = channelTable.get(clientChannelInfo.getChannel()); if (null == clientChannelInfoFound) { - channelTable.put(clientChannelInfo.getChannel().id(), clientChannelInfo); + channelTable.put(clientChannelInfo.getChannel(), clientChannelInfo); log.info("new producer connected, group: {} channel: {}", group, clientChannelInfo.toString()); } @@ -291,9 +351,9 @@ public void unregisterProducer(final String group, final ClientChannelInfo clien try { if (this.groupChannelLock.tryLock(LockTimeoutMillis, TimeUnit.MILLISECONDS)) { try { - HashMap channelTable = this.groupChannelTable.get(group); + HashMap channelTable = this.groupChannelTable.get(group); if (null != channelTable && !channelTable.isEmpty()) { - ClientChannelInfo old = channelTable.remove(clientChannelInfo.getChannel().id()); + ClientChannelInfo old = channelTable.remove(clientChannelInfo.getChannel()); if (old != null) { log.info("unregister a producer[{}] from groupChannelTable {}", group, clientChannelInfo.toString()); @@ -310,7 +370,7 @@ public void unregisterProducer(final String group, final ClientChannelInfo clien } } else { - log.warn("ProducerManager registerProducer lock timeout"); + log.warn("ProducerManager unregisterProducer lock timeout"); } } catch (InterruptedException e) { diff --git a/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/client/net/Broker2Client.java b/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/client/net/Broker2Client.java new file mode 100644 index 00000000..e9470320 --- /dev/null +++ b/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/client/net/Broker2Client.java @@ -0,0 +1,269 @@ +/** + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.rocketmq.broker.client.net; + +import io.netty.channel.Channel; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelFutureListener; +import io.netty.channel.FileRegion; + +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.alibaba.rocketmq.broker.BrokerController; +import com.alibaba.rocketmq.broker.client.ClientChannelInfo; +import com.alibaba.rocketmq.broker.pagecache.OneMessageTransfer; +import com.alibaba.rocketmq.common.MQVersion; +import com.alibaba.rocketmq.common.TopicConfig; +import com.alibaba.rocketmq.common.UtilAll; +import com.alibaba.rocketmq.common.constant.LoggerName; +import com.alibaba.rocketmq.common.message.MessageQueue; +import com.alibaba.rocketmq.common.protocol.MQProtos.MQRequestCode; +import com.alibaba.rocketmq.common.protocol.body.GetConsumerStatusBody; +import com.alibaba.rocketmq.common.protocol.body.ResetOffsetBody; +import com.alibaba.rocketmq.common.protocol.header.CheckTransactionStateRequestHeader; +import com.alibaba.rocketmq.common.protocol.header.GetConsumerStatusRequestHeader; +import com.alibaba.rocketmq.common.protocol.header.NotifyConsumerIdsChangedRequestHeader; +import com.alibaba.rocketmq.common.protocol.header.ResetOffsetRequestHeader; +import com.alibaba.rocketmq.remoting.common.RemotingHelper; +import com.alibaba.rocketmq.remoting.protocol.RemotingCommand; +import com.alibaba.rocketmq.remoting.protocol.RemotingProtos; +import com.alibaba.rocketmq.store.SelectMapedBufferResult; + + +/** + * Broker主动调用客户端接口 + * + * @author shijia.wxr + * @since 2013-7-26 + */ +public class Broker2Client { + private static final Logger log = LoggerFactory.getLogger(LoggerName.BrokerLoggerName); + private final BrokerController brokerController; + + + public Broker2Client(BrokerController brokerController) { + this.brokerController = brokerController; + } + + + /** + * Broker主动回查Producer事务状态,Oneway + */ + public void checkProducerTransactionState(// + final Channel channel,// + final CheckTransactionStateRequestHeader requestHeader,// + final SelectMapedBufferResult selectMapedBufferResult// + ) { + RemotingCommand request = + RemotingCommand.createRequestCommand(MQRequestCode.CHECK_TRANSACTION_STATE_VALUE, + requestHeader); + request.markOnewayRPC(); + + try { + FileRegion fileRegion = + new OneMessageTransfer(request.encodeHeader(selectMapedBufferResult.getSize()), + selectMapedBufferResult); + channel.writeAndFlush(fileRegion).addListener(new ChannelFutureListener() { + @Override + public void operationComplete(ChannelFuture future) throws Exception { + selectMapedBufferResult.release(); + if (!future.isSuccess()) { + log.error("invokeProducer failed,", future.cause()); + } + } + }); + } + catch (Throwable e) { + log.error("invokeProducer exception", e); + selectMapedBufferResult.release(); + } + } + + + /** + * Broker主动通知Consumer,Id列表发生变化,Oneway + */ + public void notifyConsumerIdsChanged(// + final Channel channel,// + final String consumerGroup// + ) { + NotifyConsumerIdsChangedRequestHeader requestHeader = new NotifyConsumerIdsChangedRequestHeader(); + requestHeader.setConsumerGroup(consumerGroup); + RemotingCommand request = + RemotingCommand.createRequestCommand(MQRequestCode.NOTIFY_CONSUMER_IDS_CHANGED_VALUE, + requestHeader); + + try { + this.brokerController.getRemotingServer().invokeOneway(channel, request, 1000); + } + catch (Exception e) { + log.error("notifyConsumerIdsChanged exception, " + consumerGroup, e); + } + } + + + /** + * Broker 主动通知 Consumer,offset 需要进行重置列表发生变化 + */ + public RemotingCommand resetOffset(String topic, String group, long timeStamp, boolean isForce) { + final RemotingCommand response = RemotingCommand.createResponseCommand(null); + + TopicConfig topicConfig = this.brokerController.getTopicConfigManager().selectTopicConfig(topic); + if (null == topicConfig) { + log.error("[reset-offset] reset offset failed, no topic in this broker. topic={}", topic); + response.setCode(RemotingProtos.ResponseCode.SYSTEM_ERROR_VALUE); + response.setRemark("[reset-offset] reset offset failed, no topic in this broker. topic=" + topic); + return response; + } + + Map offsetTable = new HashMap(); + for (int i = 0; i < topicConfig.getWriteQueueNums(); i++) { + MessageQueue mq = new MessageQueue(); + mq.setBrokerName(this.brokerController.getBrokerConfig().getBrokerName()); + mq.setTopic(topic); + mq.setQueueId(i); + + long consumerOffset = + this.brokerController.getConsumerOffsetManager().queryOffset(group, topic, i); + long timeStampOffset = + this.brokerController.getMessageStore().getOffsetInQueueByTime(topic, i, timeStamp); + if (isForce || timeStampOffset < consumerOffset) { + offsetTable.put(mq, timeStampOffset); + } + else { + offsetTable.put(mq, consumerOffset); + } + } + + ResetOffsetRequestHeader requestHeader = new ResetOffsetRequestHeader(); + requestHeader.setTopic(topic); + requestHeader.setGroup(group); + requestHeader.setTimestamp(timeStamp); + RemotingCommand request = + RemotingCommand.createRequestCommand(MQRequestCode.RESET_CONSUMER_CLIENT_OFFSET_VALUE, + requestHeader); + ResetOffsetBody body = new ResetOffsetBody(); + body.setOffsetTable(offsetTable); + request.setBody(body.encode()); + + ConcurrentHashMap channelInfoTable = + this.brokerController.getConsumerManager().getConsumerGroupInfo(group).getChannelInfoTable(); + for (Channel channel : channelInfoTable.keySet()) { + int version = channelInfoTable.get(channel).getVersion(); + if (version >= MQVersion.Version.V3_0_7_SNAPSHOT.ordinal()) { + try { + this.brokerController.getRemotingServer().invokeOneway(channel, request, 5000); + log.info("[reset-offset] reset offset success. topic={}, group={}, clientId={}", + new Object[] { topic, group, channelInfoTable.get(channel).getClientId() }); + } + catch (Exception e) { + log.error("[reset-offset] reset offset exception. topic={}, group={}", + new Object[] { topic, group }, e); + } + } + else { + // 如果有一个客户端是不支持该功能的,则直接返回错误,需要应用方升级。 + response.setCode(RemotingProtos.ResponseCode.SYSTEM_ERROR_VALUE); + response.setRemark("the client does not support this feature. version=" + version); + log.warn("[reset-offset] the client does not support this feature. version={}", + RemotingHelper.parseChannelRemoteAddr(channel), version); + return response; + } + } + + response.setCode(RemotingProtos.ResponseCode.SUCCESS_VALUE); + ResetOffsetBody resBody = new ResetOffsetBody(); + resBody.setOffsetTable(offsetTable); + response.setBody(resBody.encode()); + return response; + } + + + /** + * Broker主动获取Consumer端的消息情况 + */ + public RemotingCommand getConsumeStatus(String topic, String group, String originClientId) { + final RemotingCommand result = RemotingCommand.createResponseCommand(null); + + GetConsumerStatusRequestHeader requestHeader = new GetConsumerStatusRequestHeader(); + requestHeader.setTopic(topic); + requestHeader.setGroup(group); + RemotingCommand request = + RemotingCommand.createRequestCommand(MQRequestCode.GET_CONSUMER_STATUS_FROM_CLIENT_VALUE, + requestHeader); + + Map> consumerStatusTable = + new HashMap>(); + ConcurrentHashMap channelInfoTable = + this.brokerController.getConsumerManager().getConsumerGroupInfo(group).getChannelInfoTable(); + for (Channel channel : channelInfoTable.keySet()) { + int version = channelInfoTable.get(channel).getVersion(); + String clientId = channelInfoTable.get(channel).getClientId(); + if (version < MQVersion.Version.V3_0_7_SNAPSHOT.ordinal()) { + // 如果有一个客户端是不支持该功能的,则直接返回错误,需要应用方升级。 + result.setCode(RemotingProtos.ResponseCode.SYSTEM_ERROR_VALUE); + result.setRemark("the client does not support this feature. version=" + version); + log.warn("[reset-offset] the client does not support this feature. version={}", + RemotingHelper.parseChannelRemoteAddr(channel), version); + return result; + } + else if (UtilAll.isBlank(originClientId) || originClientId.equals(clientId)) { + // 不指定 originClientId 则对所有的 client 进行处理;若指定 originClientId 则只对当前 + // originClientId 进行处理 + try { + RemotingCommand response = + this.brokerController.getRemotingServer().invokeSync(channel, request, 5000); + assert response != null; + switch (response.getCode()) { + case RemotingProtos.ResponseCode.SUCCESS_VALUE: { + if (response.getBody() != null) { + GetConsumerStatusBody body = + GetConsumerStatusBody.decode(response.getBody(), + GetConsumerStatusBody.class); + + consumerStatusTable.put(clientId, body.getMessageQueueTable()); + log.info("get consumer status success. topic={}, group={}, channelRemoteAddr={}", + new Object[] { topic, group, clientId }); + } + } + default: + break; + } + } + catch (Exception e) { + log.error("get consumer status exception. topic={}, group={}, offset={}", + new Object[] { topic, group }, e); + } + + // 若指定 originClientId 相应的 client 处理完成,则退出循环 + if (!UtilAll.isBlank(originClientId) && originClientId.equals(clientId)) { + break; + } + } + } + + result.setCode(RemotingProtos.ResponseCode.SUCCESS_VALUE); + GetConsumerStatusBody resBody = new GetConsumerStatusBody(); + resBody.setConsumerTable(consumerStatusTable); + result.setBody(resBody.encode()); + return result; + } +} diff --git a/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/client/rebalance/RebalanceLockManager.java b/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/client/rebalance/RebalanceLockManager.java new file mode 100644 index 00000000..9fc55bb3 --- /dev/null +++ b/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/client/rebalance/RebalanceLockManager.java @@ -0,0 +1,312 @@ +/** + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.rocketmq.broker.client.rebalance; + +import java.util.HashSet; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.alibaba.rocketmq.common.constant.LoggerName; +import com.alibaba.rocketmq.common.message.MessageQueue; + + +/** + * 顺序消息争抢队列锁 + * + * @author shijia.wxr + * @since 2013-6-26 + */ +public class RebalanceLockManager { + private static final Logger log = LoggerFactory.getLogger(LoggerName.RebalanceLockLoggerName); + private final static long RebalanceLockMaxLiveTime = Long.parseLong(System.getProperty( + "rocketmq.broker.rebalance.lockMaxLiveTime", "60000")); + private final Lock lock = new ReentrantLock(); + private final ConcurrentHashMap> mqLockTable = + new ConcurrentHashMap>(1024); + + class LockEntry { + private String clientId; + private volatile long lastUpdateTimestamp = System.currentTimeMillis(); + + + public String getClientId() { + return clientId; + } + + + public void setClientId(String clientId) { + this.clientId = clientId; + } + + + public long getLastUpdateTimestamp() { + return lastUpdateTimestamp; + } + + + public void setLastUpdateTimestamp(long lastUpdateTimestamp) { + this.lastUpdateTimestamp = lastUpdateTimestamp; + } + + + public boolean isExpired() { + boolean expired = + (System.currentTimeMillis() - this.lastUpdateTimestamp) > RebalanceLockMaxLiveTime; + + return expired; + } + + + public boolean isLocked(final String clientId) { + boolean eq = this.clientId.equals(clientId); + return eq && !this.isExpired(); + } + } + + + private boolean isLocked(final String group, final MessageQueue mq, final String clientId) { + ConcurrentHashMap groupValue = this.mqLockTable.get(group); + if (groupValue != null) { + LockEntry lockEntry = groupValue.get(mq); + if (lockEntry != null) { + boolean locked = lockEntry.isLocked(clientId); + if (locked) { + lockEntry.setLastUpdateTimestamp(System.currentTimeMillis()); + } + + return locked; + } + } + + return false; + } + + + /** + * 尝试锁队列 + * + * @return 是否lock成功 + */ + public boolean tryLock(final String group, final MessageQueue mq, final String clientId) { + // 没有被锁住 + if (!this.isLocked(group, mq, clientId)) { + try { + this.lock.lockInterruptibly(); + try { + ConcurrentHashMap groupValue = this.mqLockTable.get(group); + if (null == groupValue) { + groupValue = new ConcurrentHashMap(32); + this.mqLockTable.put(group, groupValue); + } + + LockEntry lockEntry = groupValue.get(mq); + if (null == lockEntry) { + lockEntry = new LockEntry(); + lockEntry.setClientId(clientId); + groupValue.put(mq, lockEntry); + log.info("tryLock, message queue not locked, I got it. Group: {} NewClientId: {} {}", // + group, // + clientId, // + mq); + } + + if (lockEntry.isLocked(clientId)) { + lockEntry.setLastUpdateTimestamp(System.currentTimeMillis()); + return true; + } + + String oldClientId = lockEntry.getClientId(); + + // 锁已经过期,抢占它 + if (lockEntry.isExpired()) { + lockEntry.setClientId(clientId); + lockEntry.setLastUpdateTimestamp(System.currentTimeMillis()); + log.warn( + "tryLock, message queue lock expired, I got it. Group: {} OldClientId: {} NewClientId: {} {}", // + group, // + oldClientId, // + clientId, // + mq); + return true; + } + + // 锁被别的Client占用 + log.warn( + "tryLock, message queue locked by other client. Group: {} OtherClientId: {} NewClientId: {} {}", // + group, // + oldClientId, // + clientId, // + mq); + return false; + } + finally { + this.lock.unlock(); + } + } + catch (InterruptedException e) { + log.error("putMessage exception", e); + } + } + // 已经锁住,尝试更新时间 + else { + // isLocked 中已经更新了时间,这里不需要再更新 + } + + return true; + } + + + /** + * 批量方式锁队列,返回锁定成功的队列集合 + * + * @return 是否lock成功 + */ + public Set tryLockBatch(final String group, final Set mqs, + final String clientId) { + Set lockedMqs = new HashSet(mqs.size()); + Set notLockedMqs = new HashSet(mqs.size()); + + // 先通过不加锁的方式尝试查看哪些锁定,哪些没锁定 + for (MessageQueue mq : mqs) { + if (this.isLocked(group, mq, clientId)) { + lockedMqs.add(mq); + } + else { + notLockedMqs.add(mq); + } + } + + if (!notLockedMqs.isEmpty()) { + try { + this.lock.lockInterruptibly(); + try { + ConcurrentHashMap groupValue = this.mqLockTable.get(group); + if (null == groupValue) { + groupValue = new ConcurrentHashMap(32); + this.mqLockTable.put(group, groupValue); + } + + // 遍历没有锁住的队列 + for (MessageQueue mq : notLockedMqs) { + LockEntry lockEntry = groupValue.get(mq); + if (null == lockEntry) { + lockEntry = new LockEntry(); + lockEntry.setClientId(clientId); + groupValue.put(mq, lockEntry); + log.info( + "tryLockBatch, message queue not locked, I got it. Group: {} NewClientId: {} {}", // + group, // + clientId, // + mq); + } + + // 已经锁定 + if (lockEntry.isLocked(clientId)) { + lockEntry.setLastUpdateTimestamp(System.currentTimeMillis()); + lockedMqs.add(mq); + continue; + } + + String oldClientId = lockEntry.getClientId(); + + // 锁已经过期,抢占它 + if (lockEntry.isExpired()) { + lockEntry.setClientId(clientId); + lockEntry.setLastUpdateTimestamp(System.currentTimeMillis()); + log.warn( + "tryLockBatch, message queue lock expired, I got it. Group: {} OldClientId: {} NewClientId: {} {}", // + group, // + oldClientId, // + clientId, // + mq); + lockedMqs.add(mq); + continue; + } + + // 锁被别的Client占用 + log.warn( + "tryLockBatch, message queue locked by other client. Group: {} OtherClientId: {} NewClientId: {} {}", // + group, // + oldClientId, // + clientId, // + mq); + } + } + finally { + this.lock.unlock(); + } + } + catch (InterruptedException e) { + log.error("putMessage exception", e); + } + } + + return lockedMqs; + } + + + public void unlockBatch(final String group, final Set mqs, final String clientId) { + try { + this.lock.lockInterruptibly(); + try { + ConcurrentHashMap groupValue = this.mqLockTable.get(group); + if (null != groupValue) { + for (MessageQueue mq : mqs) { + LockEntry lockEntry = groupValue.get(mq); + if (null != lockEntry) { + if (lockEntry.getClientId().equals(clientId)) { + groupValue.remove(mq); + log.info("unlockBatch, Group: {} {} {}",// + group, // + mq, // + clientId); + } + else { + log.warn("unlockBatch, but mq locked by other client: {}, Group: {} {} {}",// + lockEntry.getClientId(), // + group, // + mq, // + clientId); + } + } + else { + log.warn("unlockBatch, but mq not locked, Group: {} {} {}",// + group, // + mq, // + clientId); + } + } + } + else { + log.warn("unlockBatch, group not exist, Group: {} {}",// + group, // + clientId); + } + } + finally { + this.lock.unlock(); + } + } + catch (InterruptedException e) { + log.error("putMessage exception", e); + } + } +} diff --git a/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/digestlog/DigestLogManager.java b/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/digestlog/DigestLogManager.java new file mode 100644 index 00000000..e5ee3bf3 --- /dev/null +++ b/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/digestlog/DigestLogManager.java @@ -0,0 +1,101 @@ +/** + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.rocketmq.broker.digestlog; + +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.TimeUnit; + +import com.alibaba.rocketmq.broker.BrokerController; + + +/** + * 统计管理器 + * + * @author 菱叶 + * @since 2013-7-18 + */ +public class DigestLogManager { + + private final boolean startRealTimeStat = Boolean.valueOf(System + .getProperty("meta.realtime.stat", "true")); + private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1, + new ThreadFactory() { + @Override + public Thread newThread(Runnable r) { + return new Thread(r, "DigestLogPrintSchedule"); + } + }); + private final PutStatsMoniter putStatsMoniter; + private final GetStatsMoniter getStatsMoniter; + private final StoreStatsMoniter storeStatsMoniter; + + + public DigestLogManager(BrokerController brokerController) { + putStatsMoniter = new PutStatsMoniter(brokerController); + getStatsMoniter = new GetStatsMoniter(brokerController); + storeStatsMoniter = new StoreStatsMoniter(brokerController); + } + + + public void init() { + + } + + + public void start() { + if (startRealTimeStat) { + scheduler.scheduleWithFixedDelay(new DigestPrintOut(), 10, 20, TimeUnit.SECONDS); + Runtime.getRuntime().addShutdownHook(new Thread() { + @Override + public void run() { + scheduler.shutdown(); + } + }); + } + } + + + public void dispose() { + scheduler.shutdown(); + } + + class DigestPrintOut implements Runnable { + @Override + public void run() { + putStatsMoniter.tolog(); + getStatsMoniter.tolog(); + storeStatsMoniter.tolog(); + } + } + + + public PutStatsMoniter getPutStatsMoniter() { + return putStatsMoniter; + } + + + public StoreStatsMoniter getStoreStatsMoniter() { + return storeStatsMoniter; + } + + + public GetStatsMoniter getGetStatsMoniter() { + return getStatsMoniter; + } + +} diff --git a/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/digestlog/GetStatsMoniter.java b/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/digestlog/GetStatsMoniter.java new file mode 100644 index 00000000..f06f95f4 --- /dev/null +++ b/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/digestlog/GetStatsMoniter.java @@ -0,0 +1,91 @@ +/** + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.rocketmq.broker.digestlog; + +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.alibaba.rocketmq.broker.BrokerController; +import com.alibaba.rocketmq.store.DefaultMessageStore; + + +/** + * 拉消息统计 + * + * @author 菱叶 + * @since 2013-7-18 + */ +public class GetStatsMoniter { + private static final Logger log = LoggerFactory.getLogger("GetStatsMoniter"); + private BrokerController brokerController; + private static final String TOPIC_GROUP_SEPARATOR = "@"; + private Map> offsetTableLast = + new HashMap>(); + + + public GetStatsMoniter(BrokerController brokerController) { + this.brokerController = brokerController; + } + + + public void tolog() { + Map> offsetTable = + brokerController.getConsumerOffsetManager().getOffsetTable(); + DefaultMessageStore defaultMessageStore = (DefaultMessageStore) brokerController.getMessageStore(); + for (String key : offsetTable.keySet()) { + String[] strs = key.split(TOPIC_GROUP_SEPARATOR); + String topic = strs[0]; + String group = strs[1]; + for (Integer queueId : offsetTable.get(key).keySet()) { + long nowvalue = offsetTable.get(key).get(queueId); + long lastvalue = getLastValue(key, queueId, nowvalue); + offsetTableLast.get(key).put(queueId, nowvalue); + if ((nowvalue - lastvalue) > 0) { + StringBuffer sb = new StringBuffer(); + sb.append("ClientGetConut").append(","); + sb.append("Topic[").append(topic).append("],"); + sb.append("Mq[") + .append(brokerController.getBrokerConfig().getBrokerName() + "-" + queueId) + .append("],"); + sb.append("Group[").append(group).append("],"); + sb.append("Total[").append(nowvalue - lastvalue).append("]"); + log.info(sb.toString()); + } + + } + + } + } + + + private long getLastValue(String key, Integer queueId, long nowValue) { + if (this.offsetTableLast.get(key) == null) { + this.offsetTableLast.put(key, new HashMap()); + this.offsetTableLast.get(key).put(queueId, nowValue); + return 0; + } + else if (this.offsetTableLast.get(key).get(queueId) == null) { + offsetTableLast.get(key).put(queueId, nowValue); + return 0; + } + return this.offsetTableLast.get(key).get(queueId); + } + +} diff --git a/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/digestlog/PullmsgLiveMoniter.java b/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/digestlog/PullmsgLiveMoniter.java new file mode 100644 index 00000000..82e052b0 --- /dev/null +++ b/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/digestlog/PullmsgLiveMoniter.java @@ -0,0 +1,25 @@ +package com.alibaba.rocketmq.broker.digestlog; + +import io.netty.channel.Channel; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.alibaba.rocketmq.remoting.common.RemotingHelper; +import com.alibaba.rocketmq.remoting.protocol.RemotingCommand; +import com.alibaba.rocketmq.store.GetMessageResult; + + +public class PullmsgLiveMoniter { + + private static final Logger log = LoggerFactory.getLogger("PullmsgLiveMoniter"); + + + public static void printProcessRequestLive(Channel channel, RemotingCommand request, + GetMessageResult getMessageResult) { + if (log.isInfoEnabled()) { + log.info("receive [{}] PullMessage request command[{}] and return result [{}] ", + RemotingHelper.parseChannelRemoteName(channel), request, getMessageResult); + } + } +} diff --git a/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/digestlog/PutStatsMoniter.java b/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/digestlog/PutStatsMoniter.java new file mode 100644 index 00000000..0cb288b0 --- /dev/null +++ b/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/digestlog/PutStatsMoniter.java @@ -0,0 +1,79 @@ +/** + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.rocketmq.broker.digestlog; + +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.atomic.AtomicLong; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.alibaba.rocketmq.broker.BrokerController; +import com.alibaba.rocketmq.store.DefaultMessageStore; + + +/** + * 发消息统计 + * + * @author 菱叶 + * @since 2013-7-18 + */ +public class PutStatsMoniter { + private static final Logger log = LoggerFactory.getLogger("PutStatsMoniter"); + private BrokerController brokerController; + + private final Map putMessageTopicTimesTotalLast = new HashMap(); + private final Map putMessageTopicSizeTotalLast = new HashMap(); + + + public PutStatsMoniter(BrokerController brokerController) { + this.brokerController = brokerController; + } + + + public void tolog() { + DefaultMessageStore defaultMessageStore = (DefaultMessageStore) brokerController.getMessageStore(); + Map putMessageTopicTimesTotal = + defaultMessageStore.getStoreStatsService().getPutMessageTopicTimesTotal(); + Map putMessageTopicSizeTotal = + defaultMessageStore.getStoreStatsService().getPutMessageTopicSizeTotal(); + for (String topic : putMessageTopicTimesTotal.keySet()) { + long putMessageTopicTimesTotalValue = putMessageTopicTimesTotal.get(topic).get(); + long putMessageTopicSizeTotalValue = putMessageTopicSizeTotal.get(topic).get(); + long putMessageTopicTimesTotalValueLast = + putMessageTopicTimesTotalLast.get(topic) == null ? 0 : putMessageTopicTimesTotalLast + .get(topic); + long putMessageTopicSizeTotalValueLast = + putMessageTopicSizeTotalLast.get(topic) == null ? 0 : putMessageTopicSizeTotalLast + .get(topic); + putMessageTopicTimesTotalLast.put(topic, putMessageTopicTimesTotalValue); + putMessageTopicSizeTotalLast.put(topic, putMessageTopicSizeTotalValue); + if ((putMessageTopicTimesTotalValue - putMessageTopicTimesTotalValueLast + + putMessageTopicSizeTotalValue - putMessageTopicSizeTotalValueLast) > 0) { + StringBuffer sb = new StringBuffer(); + sb.append("ClientPutCount").append(","); + sb.append("Topic[").append(topic).append("],"); + sb.append("Total[") + .append(putMessageTopicTimesTotalValue - putMessageTopicTimesTotalValueLast).append("],"); + sb.append("TotalSize[") + .append(putMessageTopicSizeTotalValue - putMessageTopicSizeTotalValueLast).append("]"); + log.info(sb.toString()); + } + } + } + +} diff --git a/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/digestlog/SendbackmsgLiveMoniter.java b/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/digestlog/SendbackmsgLiveMoniter.java new file mode 100644 index 00000000..0922fbbb --- /dev/null +++ b/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/digestlog/SendbackmsgLiveMoniter.java @@ -0,0 +1,26 @@ +package com.alibaba.rocketmq.broker.digestlog; + +import io.netty.channel.Channel; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.alibaba.rocketmq.remoting.common.RemotingHelper; +import com.alibaba.rocketmq.remoting.protocol.RemotingCommand; +import com.alibaba.rocketmq.store.PutMessageResult; + + +public class SendbackmsgLiveMoniter { + private static final Logger log = LoggerFactory.getLogger("SendbackmsgLiveMoniter"); + + + public static void printProcessSendmsgRequestLive(Channel channel, RemotingCommand request, + PutMessageResult putMessageResult, int delayLevel, int reconsumeTimes) { + if (log.isInfoEnabled()) { + log.info( + "receive [{}] SendBackMessage request command[{}] , this msg ReconsumeTimes[{}] and DelayLevel [{}]. return result [{}] ", + RemotingHelper.parseChannelRemoteName(channel), request, reconsumeTimes, delayLevel, + putMessageResult); + } + } +} diff --git a/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/digestlog/SendmsgLiveMoniter.java b/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/digestlog/SendmsgLiveMoniter.java new file mode 100644 index 00000000..e8f6107a --- /dev/null +++ b/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/digestlog/SendmsgLiveMoniter.java @@ -0,0 +1,24 @@ +package com.alibaba.rocketmq.broker.digestlog; + +import io.netty.channel.Channel; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.alibaba.rocketmq.remoting.common.RemotingHelper; +import com.alibaba.rocketmq.remoting.protocol.RemotingCommand; +import com.alibaba.rocketmq.store.PutMessageResult; + + +public class SendmsgLiveMoniter { + private static final Logger log = LoggerFactory.getLogger("SendmsgLiveMoniter"); + + + public static void printProcessSendmsgRequestLive(Channel channel, RemotingCommand request, + PutMessageResult putMessageResult) { + if (log.isInfoEnabled()) { + log.info("receive [{}] SendMessage request command[{}] and return result [{}] ", + RemotingHelper.parseChannelRemoteName(channel), request, putMessageResult); + } + } +} diff --git a/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/digestlog/StoreStatsMoniter.java b/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/digestlog/StoreStatsMoniter.java new file mode 100644 index 00000000..b69e4833 --- /dev/null +++ b/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/digestlog/StoreStatsMoniter.java @@ -0,0 +1,71 @@ +/** + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.rocketmq.broker.digestlog; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.alibaba.rocketmq.broker.BrokerController; +import com.alibaba.rocketmq.store.DefaultMessageStore; + + +/** + * 存储统计 + * + * @author 菱叶 + * @since 2013-7-18 + */ +public class StoreStatsMoniter { + private static final Logger log = LoggerFactory.getLogger("StoreStatsMoniter"); + private static final String TOPIC_GROUP_SEPARATOR = "@"; + private BrokerController brokerController; + + + // + + public StoreStatsMoniter(BrokerController brokerController) { + this.brokerController = brokerController; + } + + + public void tolog() { + Map> offsetTable = + brokerController.getConsumerOffsetManager().getOffsetTable(); + DefaultMessageStore defaultMessageStore = (DefaultMessageStore) brokerController.getMessageStore(); + for (String key : offsetTable.keySet()) { + String[] strs = key.split(TOPIC_GROUP_SEPARATOR); + String topic = strs[0]; + String group = strs[1]; + for (Integer queueId : offsetTable.get(key).keySet()) { + long maxoffsize = defaultMessageStore.getMaxOffsetInQuque(topic, queueId); + StringBuffer sb = new StringBuffer(); + sb.append("Client Put And get Count").append(","); + sb.append("Topic[").append(topic).append("],"); + sb.append("Mq[").append(brokerController.getBrokerConfig().getBrokerName() + "-" + queueId) + .append("],"); + sb.append("PutOffset[").append(maxoffsize).append("],"); + sb.append("group[").append(group).append("],"); + sb.append("GetOffset[").append(offsetTable.get(key).get(queueId)).append("]"); + log.info(sb.toString()); + } + + } + } + +} diff --git a/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/digestlog/UpdateCommitOffsetMoniter.java b/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/digestlog/UpdateCommitOffsetMoniter.java new file mode 100644 index 00000000..aa454f09 --- /dev/null +++ b/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/digestlog/UpdateCommitOffsetMoniter.java @@ -0,0 +1,25 @@ +package com.alibaba.rocketmq.broker.digestlog; + +import io.netty.channel.Channel; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.alibaba.rocketmq.common.protocol.header.UpdateConsumerOffsetRequestHeader; +import com.alibaba.rocketmq.remoting.common.RemotingHelper; + + +public class UpdateCommitOffsetMoniter { + + private static final Logger log = LoggerFactory.getLogger("UpdateCommitOffsetMoniter"); + + + public static void printUpdatecommit(Channel channel, UpdateConsumerOffsetRequestHeader requestHeader) { + if (log.isInfoEnabled()) { + log.info( + "client [{}] updateConsumeroffset ConsumerGroup[{}] Topic[{}] QueueId[{}] CommitOffset[{}]", + RemotingHelper.parseChannelRemoteAddr(channel), requestHeader.getConsumerGroup(), + requestHeader.getTopic(), requestHeader.getQueueId(), requestHeader.getCommitOffset()); + } + } +} diff --git a/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/longpolling/ManyPullRequest.java b/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/longpolling/ManyPullRequest.java index 7b47b262..a001b961 100644 --- a/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/longpolling/ManyPullRequest.java +++ b/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/longpolling/ManyPullRequest.java @@ -1,5 +1,17 @@ /** - * $Id: ManyPullRequest.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.broker.longpolling; @@ -8,9 +20,10 @@ /** + * 长轮询请求 * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com - * + * @author shijia.wxr + * @since 2013-7-26 */ public class ManyPullRequest { private final ArrayList pullRequestList = new ArrayList(); diff --git a/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/longpolling/PullRequest.java b/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/longpolling/PullRequest.java index 47047c2f..3d578d29 100644 --- a/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/longpolling/PullRequest.java +++ b/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/longpolling/PullRequest.java @@ -1,18 +1,30 @@ /** - * $Id: PullRequest.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.broker.longpolling; -import com.alibaba.rocketmq.remoting.protocol.RemotingCommand; - import io.netty.channel.Channel; +import com.alibaba.rocketmq.remoting.protocol.RemotingCommand; + /** - * һϢ - * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * 一个拉消息请求 * + * @author shijia.wxr + * @since 2013-7-26 */ public class PullRequest { private final RemotingCommand requestCommand; diff --git a/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/longpolling/PullRequestHoldService.java b/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/longpolling/PullRequestHoldService.java index f33eda1f..3f7d4531 100644 --- a/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/longpolling/PullRequestHoldService.java +++ b/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/longpolling/PullRequestHoldService.java @@ -1,5 +1,17 @@ /** - * $Id: PullRequestHoldService.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.broker.longpolling; @@ -11,19 +23,19 @@ import org.slf4j.LoggerFactory; import com.alibaba.rocketmq.broker.BrokerController; -import com.alibaba.rocketmq.common.MixAll; import com.alibaba.rocketmq.common.ServiceThread; +import com.alibaba.rocketmq.common.constant.LoggerName; import com.alibaba.rocketmq.remoting.exception.RemotingCommandException; /** - * ϢϢHoldסȴϢ - * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * 拉消息请求管理,如果拉不到消息,则在这里Hold住,等待消息到来 * + * @author shijia.wxr + * @since 2013-7-26 */ public class PullRequestHoldService extends ServiceThread { - private static final Logger log = LoggerFactory.getLogger(MixAll.BrokerLoggerName); + private static final Logger log = LoggerFactory.getLogger(LoggerName.BrokerLoggerName); private static final String TOPIC_QUEUEID_SEPARATOR = "@"; private ConcurrentHashMap pullRequestTable = @@ -67,7 +79,8 @@ private void checkHoldRequest() { if (kArray != null && 2 == kArray.length) { String topic = kArray[0]; int queueId = Integer.parseInt(kArray[1]); - final long offset = this.brokerController.getMessageStore().getMaxOffsetInQuque(topic, queueId); + final long offset = + this.brokerController.getMessageStore().getMaxOffsetInQuque(topic, queueId); this.notifyMessageArriving(topic, queueId, offset); } } @@ -83,7 +96,7 @@ public void notifyMessageArriving(final String topic, final int queueId, final l List replayList = new ArrayList(); for (PullRequest request : requestList) { - // 鿴Ƿoffset OK + // 查看是否offset OK if (offset >= request.getPullFromThisOffset()) { try { this.brokerController.getPullMessageProcessor().excuteRequestWhenWakeup( @@ -94,7 +107,7 @@ public void notifyMessageArriving(final String topic, final int queueId, final l } continue; } - // ȡOffset + // 尝试取最新Offset else { final long newestOffset = this.brokerController.getMessageStore().getMaxOffsetInQuque(topic, queueId); @@ -110,8 +123,9 @@ public void notifyMessageArriving(final String topic, final int queueId, final l } } - // 鿴Ƿʱ - if (System.currentTimeMillis() >= (request.getSuspendTimestamp() + request.getTimeoutMillis())) { + // 查看是否超时 + if (System.currentTimeMillis() >= (request.getSuspendTimestamp() + request + .getTimeoutMillis())) { try { this.brokerController.getPullMessageProcessor().excuteRequestWhenWakeup( request.getClientChannel(), request.getRequestCommand()); @@ -122,7 +136,7 @@ public void notifyMessageArriving(final String topic, final int queueId, final l continue; } - // ǰҪ·ŻHoldб + // 当前不满足要求,重新放回Hold列表中 replayList.add(request); } diff --git a/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/offset/ConsumerOffsetManager.java b/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/offset/ConsumerOffsetManager.java index bb9873cf..5fcecb20 100644 --- a/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/offset/ConsumerOffsetManager.java +++ b/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/offset/ConsumerOffsetManager.java @@ -1,40 +1,55 @@ /** - * $Id: ConsumerOffsetManager.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.broker.offset; -import java.io.File; -import java.util.Properties; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Map.Entry; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; -import org.apache.commons.io.IOUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.alibaba.rocketmq.broker.BrokerController; -import com.alibaba.rocketmq.common.MixAll; +import com.alibaba.rocketmq.common.ConfigManager; +import com.alibaba.rocketmq.common.constant.LoggerName; +import com.alibaba.rocketmq.remoting.protocol.RemotingSerializable; /** - * Consumerѽȹ - * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * Consumer消费进度管理 * + * @author shijia.wxr + * @since 2013-8-11 */ -public class ConsumerOffsetManager { - private static final Logger log = LoggerFactory.getLogger(MixAll.BrokerLoggerName); - +public class ConsumerOffsetManager extends ConfigManager { + private static final Logger log = LoggerFactory.getLogger(LoggerName.BrokerLoggerName); private static final String TOPIC_GROUP_SEPARATOR = "@"; - private static final String QUEUEID_OFFSET_SEPARATOR = ":"; - private static final String OFFSETS_SEPARATOR = " "; - private final ConcurrentHashMap> offsetTable = + + private ConcurrentHashMap> offsetTable = new ConcurrentHashMap>(512); - private volatile ConcurrentHashMap> offsetTableLastLast; - private volatile ConcurrentHashMap> offsetTableLast; + private transient volatile ConcurrentHashMap> offsetTableLastLast; + private transient volatile ConcurrentHashMap> offsetTableLast; + private transient BrokerController brokerController; - private final BrokerController brokerController; + + public ConsumerOffsetManager() { + } public ConsumerOffsetManager(BrokerController brokerController) { @@ -42,48 +57,22 @@ public ConsumerOffsetManager(BrokerController brokerController) { } - public boolean load() { - try { - String fileName = this.brokerController.getBrokerConfig().getConsumerOffsetPath(); - String content = MixAll.file2String(fileName); - if (content != null) { - Properties prop = MixAll.string2Properties(content); - if (prop != null) { - return this.decode(prop); - } - } - } - catch (Exception e) { - } + public Set whichTopicByConsumer(final String group) { + Set topics = new HashSet(); - return true; - } - - - private boolean decode(final Properties prop) { - Set keyset = prop.keySet(); - for (Object object : keyset) { - String key = object.toString(); - String value = prop.getProperty(key); - if (value != null) { - String[] items = value.split(OFFSETS_SEPARATOR); - if (items != null) { - for (String item : items) { - String[] pair = item.split(QUEUEID_OFFSET_SEPARATOR); - try { - int queueId = Integer.parseInt(pair[0]); - long offset = Long.parseLong(pair[1]); - this.commitOffset(key, queueId, offset); - } - catch (NumberFormatException e) { - e.printStackTrace(); - } - } + Iterator>> it = this.offsetTable.entrySet().iterator(); + while (it.hasNext()) { + Entry> next = it.next(); + String topicAtGroup = next.getKey(); + String[] arrays = topicAtGroup.split(TOPIC_GROUP_SEPARATOR); + if (arrays != null && arrays.length == 2) { + if (group.equals(arrays[1])) { + topics.add(arrays[0]); } } } - return true; + return topics; } @@ -100,7 +89,7 @@ private static ConcurrentHashMap> clone Long offset = map.get(queueId); Integer queueIdNew = new Integer(queueId.intValue()); Long offsetNew = new Long(offset.longValue()); - map.put(queueIdNew, offsetNew); + mapNew.put(queueIdNew, offsetNew); } String topicgroupNew = new String(topicgroup); @@ -112,64 +101,10 @@ private static ConcurrentHashMap> clone } - private String encode() { - StringBuilder result = new StringBuilder(); - - for (String topicgroup : this.offsetTable.keySet()) { - ConcurrentHashMap map = this.offsetTable.get(topicgroup); - if (map != null) { - StringBuilder sb = new StringBuilder(); - sb.append(topicgroup); - sb.append("="); - boolean first = true; - for (Integer queueId : map.keySet()) { - Long offset = map.get(queueId); - if (offset != null) { - String item = queueId + QUEUEID_OFFSET_SEPARATOR + offset; - if (!first) { - sb.append(OFFSETS_SEPARATOR); - } - sb.append(item); - first = false; - } - } - - if (!first) { - sb.append(IOUtils.LINE_SEPARATOR); - result.append(sb.toString()); - } - } - } - - return result.toString(); - } - - - /** - * жʱ̶߳ʱˢ - */ - public void flush() { - String content = this.encode(); - if (content != null && content.length() > 0) { - String fileName = this.brokerController.getBrokerConfig().getConsumerOffsetPath(); - boolean result = MixAll.string2File(content, fileName); - log.info("flush consumer offset, " + fileName + (result ? " OK" : " Failed")); - } - } - - - /** - * жʱ̶߳ʱˢ - */ - public void flushHistory() { - String content = this.encode(); - if (content != null && content.length() > 0) { - String fileName = - this.brokerController.getBrokerConfig().getConsumerOffsetHistoryDir() + File.separator - + System.currentTimeMillis(); - boolean result = MixAll.string2File(content, fileName); - log.info("flush consumer history offset, " + fileName + (result ? " OK" : " Failed")); - } + public long computePullTPS(final String topic, final String group) { + // topic@group + String key = topic + TOPIC_GROUP_SEPARATOR + group; + return this.computePullTPS(key); } @@ -190,10 +125,9 @@ public long computePullTPS(final String topicgroup) { if (0 == totalMsgs) return 0; - double pullTps = - totalMsgs / this.brokerController.getBrokerConfig().getFlushConsumerOffsetHistoryInterval(); - pullTps *= 1000; + totalMsgs * 1000 + / this.brokerController.getBrokerConfig().getFlushConsumerOffsetHistoryInterval(); return Double.valueOf(pullTps).longValue(); } @@ -246,4 +180,42 @@ private void commitOffset(final String key, final int queueId, final long offset map.put(queueId, offset); } } + + + public String encode() { + return this.encode(false); + } + + + public String encode(final boolean prettyFormat) { + return RemotingSerializable.toJson(this, prettyFormat); + } + + + @Override + public void decode(String jsonString) { + if (jsonString != null) { + ConsumerOffsetManager obj = + RemotingSerializable.fromJson(jsonString, ConsumerOffsetManager.class); + if (obj != null) { + this.offsetTable = obj.offsetTable; + } + } + } + + + @Override + public String configFilePath() { + return this.brokerController.getBrokerConfig().getConsumerOffsetPath(); + } + + + public ConcurrentHashMap> getOffsetTable() { + return offsetTable; + } + + + public void setOffsetTable(ConcurrentHashMap> offsetTable) { + this.offsetTable = offsetTable; + } } diff --git a/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/out/BrokerOuterAPI.java b/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/out/BrokerOuterAPI.java new file mode 100644 index 00000000..e092fb55 --- /dev/null +++ b/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/out/BrokerOuterAPI.java @@ -0,0 +1,324 @@ +/** + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.rocketmq.broker.out; + +import java.util.ArrayList; +import java.util.List; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.alibaba.rocketmq.client.exception.MQBrokerException; +import com.alibaba.rocketmq.common.constant.LoggerName; +import com.alibaba.rocketmq.common.namesrv.RegisterBrokerResult; +import com.alibaba.rocketmq.common.namesrv.TopAddressing; +import com.alibaba.rocketmq.common.protocol.MQProtos.MQRequestCode; +import com.alibaba.rocketmq.common.protocol.body.ConsumerOffsetSerializeWrapper; +import com.alibaba.rocketmq.common.protocol.body.SubscriptionGroupWrapper; +import com.alibaba.rocketmq.common.protocol.body.TopicConfigSerializeWrapper; +import com.alibaba.rocketmq.common.protocol.header.namesrv.RegisterBrokerRequestHeader; +import com.alibaba.rocketmq.common.protocol.header.namesrv.RegisterBrokerResponseHeader; +import com.alibaba.rocketmq.common.protocol.header.namesrv.UnRegisterBrokerRequestHeader; +import com.alibaba.rocketmq.remoting.RemotingClient; +import com.alibaba.rocketmq.remoting.exception.RemotingCommandException; +import com.alibaba.rocketmq.remoting.exception.RemotingConnectException; +import com.alibaba.rocketmq.remoting.exception.RemotingSendRequestException; +import com.alibaba.rocketmq.remoting.exception.RemotingTimeoutException; +import com.alibaba.rocketmq.remoting.netty.NettyClientConfig; +import com.alibaba.rocketmq.remoting.netty.NettyRemotingClient; +import com.alibaba.rocketmq.remoting.protocol.RemotingCommand; +import com.alibaba.rocketmq.remoting.protocol.RemotingProtos.ResponseCode; + + +/** + * Broker对外调用的API封装 + * + * @author shijia.wxr + * @author manhong.yqd + * @since 2013-7-3 + */ +public class BrokerOuterAPI { + private static final Logger log = LoggerFactory.getLogger(LoggerName.BrokerLoggerName); + private final RemotingClient remotingClient; + private final TopAddressing topAddressing = new TopAddressing(); + private String nameSrvAddr = null; + + + public BrokerOuterAPI(final NettyClientConfig nettyClientConfig) { + this.remotingClient = new NettyRemotingClient(nettyClientConfig); + } + + + public void start() { + this.remotingClient.start(); + } + + + public void shutdown() { + this.remotingClient.shutdown(); + } + + + public String fetchNameServerAddr() { + try { + String addrs = this.topAddressing.fetchNSAddr(); + if (addrs != null) { + if (!addrs.equals(this.nameSrvAddr)) { + log.info("name server address changed, old: " + this.nameSrvAddr + " new: " + addrs); + this.updateNameServerAddressList(addrs); + this.nameSrvAddr = addrs; + return nameSrvAddr; + } + } + } + catch (Exception e) { + log.error("fetchNameServerAddr Exception", e); + } + return nameSrvAddr; + } + + + public void updateNameServerAddressList(final String addrs) { + List lst = new ArrayList(); + String[] addrArray = addrs.split(";"); + if (addrArray != null) { + for (String addr : addrArray) { + lst.add(addr); + } + + this.remotingClient.updateNameServerAddressList(lst); + } + } + + + private RegisterBrokerResult registerBroker(// + final String namesrvAddr,// + final String clusterName,// 1 + final String brokerAddr,// 2 + final String brokerName,// 3 + final long brokerId,// 4 + final String haServerAddr,// 5 + final TopicConfigSerializeWrapper topicConfigWrapper// 6 + ) throws RemotingCommandException, MQBrokerException, RemotingConnectException, + RemotingSendRequestException, RemotingTimeoutException, InterruptedException { + RegisterBrokerRequestHeader requestHeader = new RegisterBrokerRequestHeader(); + requestHeader.setBrokerAddr(brokerAddr); + requestHeader.setBrokerId(brokerId); + requestHeader.setBrokerName(brokerName); + requestHeader.setClusterName(clusterName); + requestHeader.setHaServerAddr(haServerAddr); + RemotingCommand request = + RemotingCommand.createRequestCommand(MQRequestCode.REGISTER_BROKER_VALUE, requestHeader); + request.setBody(topicConfigWrapper.encode()); + + RemotingCommand response = this.remotingClient.invokeSync(namesrvAddr, request, 3000); + assert response != null; + switch (response.getCode()) { + case ResponseCode.SUCCESS_VALUE: { + RegisterBrokerResponseHeader responseHeader = + (RegisterBrokerResponseHeader) response + .decodeCommandCustomHeader(RegisterBrokerResponseHeader.class); + RegisterBrokerResult result = new RegisterBrokerResult(); + result.setMasterAddr(responseHeader.getMasterAddr()); + result.setHaServerAddr(responseHeader.getHaServerAddr()); + return result; + } + default: + break; + } + + throw new MQBrokerException(response.getCode(), response.getRemark()); + } + + + public RegisterBrokerResult registerBrokerAll(// + final String clusterName,// 1 + final String brokerAddr,// 2 + final String brokerName,// 3 + final long brokerId,// 4 + final String haServerAddr,// 5 + final TopicConfigSerializeWrapper topicConfigWrapper// 6 + ) { + RegisterBrokerResult registerBrokerResult = null; + + List nameServerAddressList = this.remotingClient.getNameServerAddressList(); + if (nameServerAddressList != null) { + for (String namesrvAddr : nameServerAddressList) { + try { + RegisterBrokerResult result = + this.registerBroker(namesrvAddr, clusterName, brokerAddr, brokerName, brokerId, + haServerAddr, topicConfigWrapper); + if (result != null) { + registerBrokerResult = result; + } + + log.info("register broker to name server {} OK", namesrvAddr); + } + catch (Exception e) { + log.warn("registerBroker Exception, " + namesrvAddr, e); + } + } + } + + return registerBrokerResult; + } + + + public void unregisterBroker(// + final String namesrvAddr,// + final String clusterName,// 1 + final String brokerAddr,// 2 + final String brokerName,// 3 + final long brokerId// 4 + ) throws RemotingConnectException, RemotingSendRequestException, RemotingTimeoutException, + InterruptedException, MQBrokerException { + UnRegisterBrokerRequestHeader requestHeader = new UnRegisterBrokerRequestHeader(); + requestHeader.setBrokerAddr(brokerAddr); + requestHeader.setBrokerId(brokerId); + requestHeader.setBrokerName(brokerName); + requestHeader.setClusterName(clusterName); + RemotingCommand request = + RemotingCommand.createRequestCommand(MQRequestCode.UNREGISTER_BROKER_VALUE, requestHeader); + + RemotingCommand response = this.remotingClient.invokeSync(namesrvAddr, request, 3000); + assert response != null; + switch (response.getCode()) { + case ResponseCode.SUCCESS_VALUE: { + return; + } + default: + break; + } + + throw new MQBrokerException(response.getCode(), response.getRemark()); + } + + + public void unregisterBrokerAll(// + final String clusterName,// 1 + final String brokerAddr,// 2 + final String brokerName,// 3 + final long brokerId// 4 + ) { + List nameServerAddressList = this.remotingClient.getNameServerAddressList(); + if (nameServerAddressList != null) { + for (String namesrvAddr : nameServerAddressList) { + try { + this.unregisterBroker(namesrvAddr, clusterName, brokerAddr, brokerName, brokerId); + log.info("unregisterBroker OK, NamesrvAddr: {}", namesrvAddr); + } + catch (Exception e) { + log.warn("unregisterBroker Exception, " + namesrvAddr, e); + } + } + } + } + + + public TopicConfigSerializeWrapper getAllTopicConfig(final String addr) throws RemotingConnectException, + RemotingSendRequestException, RemotingTimeoutException, InterruptedException, MQBrokerException { + RemotingCommand request = + RemotingCommand.createRequestCommand(MQRequestCode.GET_ALL_TOPIC_CONFIG_VALUE, null); + + RemotingCommand response = this.remotingClient.invokeSync(addr, request, 3000); + assert response != null; + switch (response.getCode()) { + case ResponseCode.SUCCESS_VALUE: { + return TopicConfigSerializeWrapper.decode(response.getBody(), TopicConfigSerializeWrapper.class); + } + default: + break; + } + + throw new MQBrokerException(response.getCode(), response.getRemark()); + } + + + /** + * 获取所有Consumer Offset + * + * @param addr + * @return + */ + public ConsumerOffsetSerializeWrapper getAllConsumerOffset(final String addr) + throws InterruptedException, RemotingTimeoutException, RemotingSendRequestException, + RemotingConnectException, MQBrokerException { + RemotingCommand request = + RemotingCommand.createRequestCommand(MQRequestCode.GET_ALL_CONSUMER_OFFSET_VALUE, null); + RemotingCommand response = this.remotingClient.invokeSync(addr, request, 3000); + assert response != null; + switch (response.getCode()) { + case ResponseCode.SUCCESS_VALUE: { + return ConsumerOffsetSerializeWrapper.decode(response.getBody(), + ConsumerOffsetSerializeWrapper.class); + } + default: + break; + } + + throw new MQBrokerException(response.getCode(), response.getRemark()); + } + + + /** + * 获取所有定时进度 + * + * @param addr + * @return + */ + public String getAllDelayOffset(final String addr) throws InterruptedException, RemotingTimeoutException, + RemotingSendRequestException, RemotingConnectException, MQBrokerException { + RemotingCommand request = + RemotingCommand.createRequestCommand(MQRequestCode.GET_ALL_DELAY_OFFSET_VALUE, null); + RemotingCommand response = this.remotingClient.invokeSync(addr, request, 3000); + assert response != null; + switch (response.getCode()) { + case ResponseCode.SUCCESS_VALUE: { + return new String(response.getBody()); + } + default: + break; + } + + throw new MQBrokerException(response.getCode(), response.getRemark()); + } + + + /** + * 获取订阅组配置 + * + * @param addr + * @return + */ + public SubscriptionGroupWrapper getAllSubscriptionGroupConfig(final String addr) + throws InterruptedException, RemotingTimeoutException, RemotingSendRequestException, + RemotingConnectException, MQBrokerException { + RemotingCommand request = + RemotingCommand.createRequestCommand(MQRequestCode.GET_ALL_SUBSCRIPTIONGROUP_CONFIG_VALUE, + null); + RemotingCommand response = this.remotingClient.invokeSync(addr, request, 3000); + assert response != null; + switch (response.getCode()) { + case ResponseCode.SUCCESS_VALUE: { + return SubscriptionGroupWrapper.decode(response.getBody(), SubscriptionGroupWrapper.class); + } + default: + break; + } + + throw new MQBrokerException(response.getCode(), response.getRemark()); + } +} diff --git a/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/pagecache/ManyMessageTransfer.java b/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/pagecache/ManyMessageTransfer.java index 8fa70bc4..aa7888c9 100644 --- a/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/pagecache/ManyMessageTransfer.java +++ b/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/pagecache/ManyMessageTransfer.java @@ -1,10 +1,22 @@ /** - * $Id: ManyMessageTransfer.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.broker.pagecache; -import io.netty.buffer.AbstractReferenceCounted; import io.netty.channel.FileRegion; +import io.netty.util.AbstractReferenceCounted; import java.io.IOException; import java.nio.ByteBuffer; @@ -15,12 +27,13 @@ /** - * @author vintage.wang@gmail.com shijia.wxr@taobao.com - * + * @author shijia.wxr + * @since 2013-7-26 */ public class ManyMessageTransfer extends AbstractReferenceCounted implements FileRegion { private final ByteBuffer byteBufferHeader; private final GetMessageResult getMessageResult; + private long transfered; // the bytes which was transfered already public ManyMessageTransfer(ByteBuffer byteBufferHeader, GetMessageResult getMessageResult) { @@ -31,8 +44,8 @@ public ManyMessageTransfer(ByteBuffer byteBufferHeader, GetMessageResult getMess @Override public long position() { + int pos = byteBufferHeader.position(); List messageBufferList = this.getMessageResult.getMessageBufferList(); - int pos = 0; for (ByteBuffer bb : messageBufferList) { pos += bb.position(); } @@ -42,20 +55,22 @@ public long position() { @Override public long count() { - return this.getMessageResult.getBufferTotalSize(); + return byteBufferHeader.limit() + this.getMessageResult.getBufferTotalSize(); } @Override public long transferTo(WritableByteChannel target, long position) throws IOException { if (this.byteBufferHeader.hasRemaining()) { - return target.write(this.byteBufferHeader); + transfered += target.write(this.byteBufferHeader); + return transfered; } else { List messageBufferList = this.getMessageResult.getMessageBufferList(); for (ByteBuffer bb : messageBufferList) { if (bb.hasRemaining()) { - return target.write(bb); + transfered += target.write(bb); + return transfered; } } } @@ -73,4 +88,10 @@ public void close() { protected void deallocate() { this.getMessageResult.release(); } + + + @Override + public long transfered() { + return transfered; + } } diff --git a/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/pagecache/OneMessageTransfer.java b/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/pagecache/OneMessageTransfer.java index 96108107..4f0f46ee 100644 --- a/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/pagecache/OneMessageTransfer.java +++ b/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/pagecache/OneMessageTransfer.java @@ -1,25 +1,38 @@ /** - * $Id: OneMessageTransfer.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.broker.pagecache; +import io.netty.channel.FileRegion; +import io.netty.util.AbstractReferenceCounted; + import java.io.IOException; import java.nio.ByteBuffer; import java.nio.channels.WritableByteChannel; import com.alibaba.rocketmq.store.SelectMapedBufferResult; -import io.netty.buffer.AbstractReferenceCounted; -import io.netty.channel.FileRegion; - /** - * @author vintage.wang@gmail.com shijia.wxr@taobao.com - * + * @author shijia.wxr + * @since 2013-7-26 */ public class OneMessageTransfer extends AbstractReferenceCounted implements FileRegion { private final ByteBuffer byteBufferHeader; private final SelectMapedBufferResult selectMapedBufferResult; + private long transfered; // the bytes which was transfered already public OneMessageTransfer(ByteBuffer byteBufferHeader, SelectMapedBufferResult selectMapedBufferResult) { @@ -43,10 +56,12 @@ public long count() { @Override public long transferTo(WritableByteChannel target, long position) throws IOException { if (this.byteBufferHeader.hasRemaining()) { - return target.write(this.byteBufferHeader); + transfered += target.write(this.byteBufferHeader); + return transfered; } else if (this.selectMapedBufferResult.getByteBuffer().hasRemaining()) { - return target.write(this.selectMapedBufferResult.getByteBuffer()); + transfered += target.write(this.selectMapedBufferResult.getByteBuffer()); + return transfered; } return 0; @@ -62,4 +77,10 @@ public void close() { protected void deallocate() { this.selectMapedBufferResult.release(); } + + + @Override + public long transfered() { + return transfered; + } } diff --git a/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/pagecache/QueryMessageTransfer.java b/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/pagecache/QueryMessageTransfer.java index df7c9185..b7f3c837 100644 --- a/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/pagecache/QueryMessageTransfer.java +++ b/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/pagecache/QueryMessageTransfer.java @@ -1,10 +1,22 @@ /** - * $Id: QueryMessageTransfer.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.broker.pagecache; -import io.netty.buffer.AbstractReferenceCounted; import io.netty.channel.FileRegion; +import io.netty.util.AbstractReferenceCounted; import java.io.IOException; import java.nio.ByteBuffer; @@ -15,12 +27,13 @@ /** - * @author vintage.wang@gmail.com shijia.wxr@taobao.com - * + * @author shijia.wxr + * @since 2013-7-26 */ public class QueryMessageTransfer extends AbstractReferenceCounted implements FileRegion { private final ByteBuffer byteBufferHeader; private final QueryMessageResult queryMessageResult; + private long transfered; // the bytes which was transfered already public QueryMessageTransfer(ByteBuffer byteBufferHeader, QueryMessageResult queryMessageResult) { @@ -31,8 +44,8 @@ public QueryMessageTransfer(ByteBuffer byteBufferHeader, QueryMessageResult quer @Override public long position() { + int pos = byteBufferHeader.position(); List messageBufferList = this.queryMessageResult.getMessageBufferList(); - int pos = 0; for (ByteBuffer bb : messageBufferList) { pos += bb.position(); } @@ -42,20 +55,22 @@ public long position() { @Override public long count() { - return this.queryMessageResult.getBufferTotalSize(); + return byteBufferHeader.limit() + this.queryMessageResult.getBufferTotalSize(); } @Override public long transferTo(WritableByteChannel target, long position) throws IOException { if (this.byteBufferHeader.hasRemaining()) { - return target.write(this.byteBufferHeader); + transfered += target.write(this.byteBufferHeader); + return transfered; } else { List messageBufferList = this.queryMessageResult.getMessageBufferList(); for (ByteBuffer bb : messageBufferList) { if (bb.hasRemaining()) { - return target.write(bb); + transfered += target.write(bb); + return transfered; } } } @@ -73,4 +88,10 @@ public void close() { protected void deallocate() { this.queryMessageResult.release(); } + + + @Override + public long transfered() { + return transfered; + } } diff --git a/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/processor/AdminBrokerProcessor.java b/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/processor/AdminBrokerProcessor.java index c6b6f7e7..29e0d8af 100644 --- a/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/processor/AdminBrokerProcessor.java +++ b/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/processor/AdminBrokerProcessor.java @@ -1,50 +1,98 @@ /** - * $Id: AdminBrokerProcessor.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.broker.processor; +import io.netty.channel.Channel; import io.netty.channel.ChannelHandlerContext; import java.io.UnsupportedEncodingException; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; import java.util.Properties; +import java.util.Set; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.alibaba.rocketmq.broker.BrokerController; +import com.alibaba.rocketmq.broker.client.ClientChannelInfo; +import com.alibaba.rocketmq.broker.client.ConsumerGroupInfo; +import com.alibaba.rocketmq.broker.digestlog.UpdateCommitOffsetMoniter; +import com.alibaba.rocketmq.common.MQVersion; import com.alibaba.rocketmq.common.MixAll; import com.alibaba.rocketmq.common.TopicConfig; +import com.alibaba.rocketmq.common.admin.ConsumeStats; +import com.alibaba.rocketmq.common.admin.OffsetWrapper; +import com.alibaba.rocketmq.common.admin.TopicOffset; +import com.alibaba.rocketmq.common.admin.TopicStatsTable; +import com.alibaba.rocketmq.common.constant.LoggerName; +import com.alibaba.rocketmq.common.message.MessageQueue; import com.alibaba.rocketmq.common.protocol.MQProtos.MQRequestCode; import com.alibaba.rocketmq.common.protocol.MQProtos.MQResponseCode; +import com.alibaba.rocketmq.common.protocol.body.Connection; +import com.alibaba.rocketmq.common.protocol.body.ConsumerConnection; +import com.alibaba.rocketmq.common.protocol.body.KVTable; +import com.alibaba.rocketmq.common.protocol.body.LockBatchRequestBody; +import com.alibaba.rocketmq.common.protocol.body.LockBatchResponseBody; +import com.alibaba.rocketmq.common.protocol.body.UnlockBatchRequestBody; import com.alibaba.rocketmq.common.protocol.header.CreateTopicRequestHeader; +import com.alibaba.rocketmq.common.protocol.header.DeleteSubscriptionGroupRequestHeader; import com.alibaba.rocketmq.common.protocol.header.DeleteTopicRequestHeader; import com.alibaba.rocketmq.common.protocol.header.GetAllTopicConfigResponseHeader; import com.alibaba.rocketmq.common.protocol.header.GetBrokerConfigResponseHeader; +import com.alibaba.rocketmq.common.protocol.header.GetConsumeStatsRequestHeader; +import com.alibaba.rocketmq.common.protocol.header.GetConsumerConnectionListRequestHeader; +import com.alibaba.rocketmq.common.protocol.header.GetConsumerStatusRequestHeader; import com.alibaba.rocketmq.common.protocol.header.GetEarliestMsgStoretimeRequestHeader; import com.alibaba.rocketmq.common.protocol.header.GetEarliestMsgStoretimeResponseHeader; import com.alibaba.rocketmq.common.protocol.header.GetMaxOffsetRequestHeader; import com.alibaba.rocketmq.common.protocol.header.GetMaxOffsetResponseHeader; import com.alibaba.rocketmq.common.protocol.header.GetMinOffsetRequestHeader; import com.alibaba.rocketmq.common.protocol.header.GetMinOffsetResponseHeader; +import com.alibaba.rocketmq.common.protocol.header.GetProducerConnectionListRequestHeader; +import com.alibaba.rocketmq.common.protocol.header.GetTopicStatsInfoRequestHeader; import com.alibaba.rocketmq.common.protocol.header.QueryConsumerOffsetRequestHeader; import com.alibaba.rocketmq.common.protocol.header.QueryConsumerOffsetResponseHeader; +import com.alibaba.rocketmq.common.protocol.header.ResetOffsetRequestHeader; import com.alibaba.rocketmq.common.protocol.header.SearchOffsetRequestHeader; import com.alibaba.rocketmq.common.protocol.header.SearchOffsetResponseHeader; import com.alibaba.rocketmq.common.protocol.header.UpdateConsumerOffsetRequestHeader; import com.alibaba.rocketmq.common.protocol.header.UpdateConsumerOffsetResponseHeader; +import com.alibaba.rocketmq.common.protocol.heartbeat.SubscriptionData; +import com.alibaba.rocketmq.common.subscription.SubscriptionGroupConfig; +import com.alibaba.rocketmq.remoting.common.RemotingHelper; import com.alibaba.rocketmq.remoting.exception.RemotingCommandException; import com.alibaba.rocketmq.remoting.netty.NettyRequestProcessor; import com.alibaba.rocketmq.remoting.protocol.RemotingCommand; import com.alibaba.rocketmq.remoting.protocol.RemotingProtos.ResponseCode; +import com.alibaba.rocketmq.remoting.protocol.RemotingSerializable; +import com.alibaba.rocketmq.store.DefaultMessageStore; +import com.alibaba.rocketmq.store.StoreUtil; /** - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * 管理类请求处理 * + * @author shijia.wxr + * @author manhong.yqd + * @since 2013-7-26 */ public class AdminBrokerProcessor implements NettyRequestProcessor { - private static final Logger log = LoggerFactory.getLogger(MixAll.BrokerLoggerName); - + private static final Logger log = LoggerFactory.getLogger(LoggerName.BrokerLoggerName); private final BrokerController brokerController; @@ -57,27 +105,25 @@ public AdminBrokerProcessor(final BrokerController brokerController) { public RemotingCommand processRequest(ChannelHandlerContext ctx, RemotingCommand request) throws RemotingCommandException { MQRequestCode code = MQRequestCode.valueOf(request.getCode()); - log.info("broker receive admin [" + code + "] request, " + request + " client: " - + ctx.channel().remoteAddress()); switch (code) { - // ´Topic + // 更新创建Topic case UPDATE_AND_CREATE_TOPIC: return this.updateAndCreateTopic(ctx, request); - // ɾTopic - case DELETE_TOPIC: + // 删除Topic + case DELETE_TOPIC_IN_BROKER: return this.deleteTopic(ctx, request); - // ȡTopic + // 获取Topic配置 case GET_ALL_TOPIC_CONFIG: return this.getAllTopicConfig(ctx, request); - // Broker TODO ܴڲ + // 更新Broker配置 TODO 可能存在并发问题 case UPDATE_BROKER_CONFIG: return this.updateBrokerConfig(ctx, request); - // ȡBroker + // 获取Broker配置 case GET_BROKER_CONFIG: return this.getBrokerConfig(ctx, request); - // ʱѯOffset + // 根据时间查询Offset case SEARCH_OFFSET_BY_TIMESTAMP: return this.searchOffsetByTimestamp(ctx, request); case GET_MAX_OFFSET: @@ -87,43 +133,365 @@ public RemotingCommand processRequest(ChannelHandlerContext ctx, RemotingCommand case GET_EARLIEST_MSG_STORETIME: return this.getEarliestMsgStoretime(ctx, request); - // Consumer Offset + // 更新Consumer Offset case UPDATE_CONSUMER_OFFSET: return this.updateConsumerOffset(ctx, request); case QUERY_CONSUMER_OFFSET: return this.queryConsumerOffset(ctx, request); - // ȡBrokerʱϢ + // 获取Broker运行时信息 case GET_BROKER_RUNTIME_INFO: + return this.getBrokerRuntimeInfo(ctx, request); + + // 锁队列与解锁队列 + case LOCK_BATCH_MQ: + return this.lockBatchMQ(ctx, request); + case UNLOCK_BATCH_MQ: + return this.unlockBatchMQ(ctx, request); + + // 订阅组配置 + case UPDATE_AND_CREATE_SUBSCRIPTIONGROUP: + return this.updateAndCreateSubscriptionGroup(ctx, request); + case GET_ALL_SUBSCRIPTIONGROUP_CONFIG: + return this.getAllSubscriptionGroup(ctx, request); + case DELETE_SUBSCRIPTIONGROUP: + return this.deleteSubscriptionGroup(ctx, request); + + // 统计信息,获取Topic统计信息 + case GET_TOPIC_STATS_INFO: + return this.getTopicStatsInfo(ctx, request); + + // Consumer连接管理 + case GET_CONSUMER_CONNECTION_LIST: + return this.getConsumerConnectionList(ctx, request); + // Producer连接管理 + case GET_PRODUCER_CONNECTION_LIST: + return this.getProducerConnectionList(ctx, request); + + // 查询消费进度,订阅组下的所有Topic + case GET_CONSUME_STATS: + return this.getConsumeStats(ctx, request); + case GET_ALL_CONSUMER_OFFSET: + return this.getAllConsumerOffset(ctx, request); + + // 定时进度 + case GET_ALL_DELAY_OFFSET: + return this.getAllDelayOffset(ctx, request); + + // 调用客户端重置 offset + case INVOKE_BROKER_TO_RESET_OFFSET: + return this.resetOffset(ctx, request); + + // 调用客户端订阅消息处理 + case INVOKE_BROKER_TO_GET_CONSUMER_STATUS: + return this.getConsumerStatus(ctx, request); + default: break; - case PULL_ALL_CONSUMER_OFFSET: - break; - case QUERY_BROKER_OFFSET: - break; + } - case QUERY_MESSAGE: - break; - case REGISTER_BROKER: - break; - case REGISTER_ORDER_TOPIC: - break; - case SEND_MESSAGE: - break; - case TRIGGER_DELETE_FILES: - break; - case UNREGISTER_BROKER: - break; - case UNREGISTER_ORDER_TOPIC: - break; + return null; + } - case UPDATE_NAMESRV_CONFIG: - break; - default: - break; + + private RemotingCommand getConsumeStats(ChannelHandlerContext ctx, RemotingCommand request) + throws RemotingCommandException { + final RemotingCommand response = RemotingCommand.createResponseCommand(null); + final GetConsumeStatsRequestHeader requestHeader = + (GetConsumeStatsRequestHeader) request + .decodeCommandCustomHeader(GetConsumeStatsRequestHeader.class); + + ConsumeStats consumeStats = new ConsumeStats(); + + Set topics = + this.brokerController.getConsumerOffsetManager().whichTopicByConsumer( + requestHeader.getConsumerGroup()); + + for (String topic : topics) { + TopicConfig topicConfig = this.brokerController.getTopicConfigManager().selectTopicConfig(topic); + if (null == topicConfig) { + log.warn("consumeStats, topic config not exist, {}", topic); + continue; + } + + SubscriptionData findSubscriptionData = + this.brokerController.getConsumerManager().findSubscriptionData( + requestHeader.getConsumerGroup(), topic); + if (null == findSubscriptionData) { + log.warn("consumeStats, the consumer group[{}], topic[{}] not exist", + requestHeader.getConsumerGroup(), topic); + continue; + } + + for (int i = 0; i < topicConfig.getWriteQueueNums(); i++) { + MessageQueue mq = new MessageQueue(); + mq.setTopic(topic); + mq.setBrokerName(this.brokerController.getBrokerConfig().getBrokerName()); + mq.setQueueId(i); + + OffsetWrapper offsetWrapper = new OffsetWrapper(); + + long brokerOffset = this.brokerController.getMessageStore().getMaxOffsetInQuque(topic, i); + if (brokerOffset < 0) + brokerOffset = 0; + + long consumerOffset = this.brokerController.getConsumerOffsetManager().queryOffset(// + requestHeader.getConsumerGroup(),// + topic,// + i); + if (consumerOffset < 0) + consumerOffset = 0; + + offsetWrapper.setBrokerOffset(brokerOffset); + offsetWrapper.setConsumerOffset(consumerOffset); + + // 查询消费者最后一条消息对应的时间戳 + long timeOffset = consumerOffset - 1; + if (timeOffset >= 0) { + long lastTimestamp = + this.brokerController.getMessageStore().getMessageStoreTimeStamp(topic, i, + timeOffset); + if (lastTimestamp > 0) { + offsetWrapper.setLastTimestamp(lastTimestamp); + } + } + + consumeStats.getOffsetTable().put(mq, offsetWrapper); + } + + long consumeTps = + this.brokerController.getConsumerOffsetManager().computePullTPS(topic, + requestHeader.getConsumerGroup()); + + consumeTps += consumeStats.getConsumeTps(); + consumeStats.setConsumeTps(consumeTps); } - return null; + byte[] body = consumeStats.encode(); + response.setBody(body); + response.setCode(ResponseCode.SUCCESS_VALUE); + response.setRemark(null); + return response; + } + + + private RemotingCommand getProducerConnectionList(ChannelHandlerContext ctx, RemotingCommand request) + throws RemotingCommandException { + final RemotingCommand response = RemotingCommand.createResponseCommand(null); + final GetProducerConnectionListRequestHeader requestHeader = + (GetProducerConnectionListRequestHeader) request + .decodeCommandCustomHeader(GetProducerConnectionListRequestHeader.class); + + ConsumerConnection bodydata = new ConsumerConnection(); + HashMap channelInfoHashMap = + this.brokerController.getProducerManager().getGroupChannelTable() + .get(requestHeader.getProducerGroup()); + if (channelInfoHashMap != null) { + Iterator> it = channelInfoHashMap.entrySet().iterator(); + while (it.hasNext()) { + ClientChannelInfo info = it.next().getValue(); + Connection connection = new Connection(); + connection.setClientId(info.getClientId()); + connection.setLanguage(info.getLanguage()); + connection.setVersion(info.getVersion()); + connection.setClientAddr(RemotingHelper.parseChannelRemoteAddr(info.getChannel())); + + bodydata.getConnectionSet().add(connection); + } + + byte[] body = bodydata.encode(); + response.setBody(body); + response.setCode(ResponseCode.SUCCESS_VALUE); + response.setRemark(null); + return response; + } + + response.setCode(ResponseCode.SYSTEM_ERROR_VALUE); + response.setRemark("the producer group[" + requestHeader.getProducerGroup() + "] not exist"); + return response; + } + + + private RemotingCommand getConsumerConnectionList(ChannelHandlerContext ctx, RemotingCommand request) + throws RemotingCommandException { + final RemotingCommand response = RemotingCommand.createResponseCommand(null); + final GetConsumerConnectionListRequestHeader requestHeader = + (GetConsumerConnectionListRequestHeader) request + .decodeCommandCustomHeader(GetConsumerConnectionListRequestHeader.class); + + ConsumerGroupInfo consumerGroupInfo = + this.brokerController.getConsumerManager().getConsumerGroupInfo( + requestHeader.getConsumerGroup()); + if (consumerGroupInfo != null) { + ConsumerConnection bodydata = new ConsumerConnection(); + bodydata.setConsumeFromWhere(consumerGroupInfo.getConsumeFromWhere()); + bodydata.setConsumeType(consumerGroupInfo.getConsumeType()); + bodydata.setMessageModel(consumerGroupInfo.getMessageModel()); + bodydata.getSubscriptionTable().putAll(consumerGroupInfo.getSubscriptionTable()); + + Iterator> it = + consumerGroupInfo.getChannelInfoTable().entrySet().iterator(); + while (it.hasNext()) { + ClientChannelInfo info = it.next().getValue(); + Connection connection = new Connection(); + connection.setClientId(info.getClientId()); + connection.setLanguage(info.getLanguage()); + connection.setVersion(info.getVersion()); + connection.setClientAddr(RemotingHelper.parseChannelRemoteAddr(info.getChannel())); + + bodydata.getConnectionSet().add(connection); + } + + byte[] body = bodydata.encode(); + response.setBody(body); + response.setCode(ResponseCode.SUCCESS_VALUE); + response.setRemark(null); + + return response; + } + + response.setCode(MQResponseCode.SUBSCRIPTION_GROUP_NOT_EXIST_VALUE); + response.setRemark("the consumer group[" + requestHeader.getConsumerGroup() + "] not online"); + return response; + } + + + private RemotingCommand getTopicStatsInfo(ChannelHandlerContext ctx, RemotingCommand request) + throws RemotingCommandException { + final RemotingCommand response = RemotingCommand.createResponseCommand(null); + final GetTopicStatsInfoRequestHeader requestHeader = + (GetTopicStatsInfoRequestHeader) request + .decodeCommandCustomHeader(GetTopicStatsInfoRequestHeader.class); + + final String topic = requestHeader.getTopic(); + TopicConfig topicConfig = this.brokerController.getTopicConfigManager().selectTopicConfig(topic); + if (null == topicConfig) { + response.setCode(MQResponseCode.TOPIC_NOT_EXIST_VALUE); + response.setRemark("topic[" + topic + "] not exist"); + return response; + } + + TopicStatsTable topicStatsTable = new TopicStatsTable(); + for (int i = 0; i < topicConfig.getWriteQueueNums(); i++) { + MessageQueue mq = new MessageQueue(); + mq.setTopic(topic); + mq.setBrokerName(this.brokerController.getBrokerConfig().getBrokerName()); + mq.setQueueId(i); + + TopicOffset topicOffset = new TopicOffset(); + long min = this.brokerController.getMessageStore().getMinOffsetInQuque(topic, i); + if (min < 0) + min = 0; + + long max = this.brokerController.getMessageStore().getMaxOffsetInQuque(topic, i); + if (max < 0) + max = 0; + + long timestamp = 0; + if (max > 0) { + timestamp = + this.brokerController.getMessageStore().getMessageStoreTimeStamp(topic, i, (max - 1)); + } + + topicOffset.setMinOffset(min); + topicOffset.setMaxOffset(max); + topicOffset.setLastUpdateTimestamp(timestamp); + + topicStatsTable.getOffsetTable().put(mq, topicOffset); + } + + byte[] body = topicStatsTable.encode(); + response.setBody(body); + response.setCode(ResponseCode.SUCCESS_VALUE); + response.setRemark(null); + return response; + } + + + private RemotingCommand updateAndCreateSubscriptionGroup(ChannelHandlerContext ctx, + RemotingCommand request) throws RemotingCommandException { + final RemotingCommand response = RemotingCommand.createResponseCommand(null); + + log.info("updateAndCreateSubscriptionGroup called by {}", + RemotingHelper.parseChannelRemoteAddr(ctx.channel())); + + SubscriptionGroupConfig config = + RemotingSerializable.decode(request.getBody(), SubscriptionGroupConfig.class); + if (config != null) { + this.brokerController.getSubscriptionGroupManager().updateSubscriptionGroupConfig(config); + } + + response.setCode(ResponseCode.SUCCESS_VALUE); + response.setRemark(null); + return response; + } + + + private RemotingCommand getAllSubscriptionGroup(ChannelHandlerContext ctx, RemotingCommand request) + throws RemotingCommandException { + final RemotingCommand response = RemotingCommand.createResponseCommand(null); + String content = this.brokerController.getSubscriptionGroupManager().encode(); + if (content != null && content.length() > 0) { + try { + response.setBody(content.getBytes(MixAll.DEFAULT_CHARSET)); + } + catch (UnsupportedEncodingException e) { + log.error("", e); + + response.setCode(ResponseCode.SYSTEM_ERROR_VALUE); + response.setRemark("UnsupportedEncodingException " + e); + return response; + } + } + else { + log.error("No subscription group in this broker, client: " + ctx.channel().remoteAddress()); + response.setCode(ResponseCode.SYSTEM_ERROR_VALUE); + response.setRemark("No subscription group in this broker"); + return response; + } + + response.setCode(ResponseCode.SUCCESS_VALUE); + response.setRemark(null); + + return response; + } + + + private RemotingCommand lockBatchMQ(ChannelHandlerContext ctx, RemotingCommand request) + throws RemotingCommandException { + final RemotingCommand response = RemotingCommand.createResponseCommand(null); + LockBatchRequestBody requestBody = + LockBatchRequestBody.decode(request.getBody(), LockBatchRequestBody.class); + + Set lockOKMQSet = this.brokerController.getRebalanceLockManager().tryLockBatch(// + requestBody.getConsumerGroup(),// + requestBody.getMqSet(),// + requestBody.getClientId()); + + LockBatchResponseBody responseBody = new LockBatchResponseBody(); + responseBody.setLockOKMQSet(lockOKMQSet); + + response.setBody(responseBody.encode()); + response.setCode(ResponseCode.SUCCESS_VALUE); + response.setRemark(null); + return response; + } + + + private RemotingCommand unlockBatchMQ(ChannelHandlerContext ctx, RemotingCommand request) + throws RemotingCommandException { + final RemotingCommand response = RemotingCommand.createResponseCommand(null); + UnlockBatchRequestBody requestBody = + UnlockBatchRequestBody.decode(request.getBody(), UnlockBatchRequestBody.class); + + this.brokerController.getRebalanceLockManager().unlockBatch(// + requestBody.getConsumerGroup(),// + requestBody.getMqSet(),// + requestBody.getClientId()); + + response.setCode(ResponseCode.SUCCESS_VALUE); + response.setRemark(null); + return response; } @@ -132,6 +500,17 @@ private RemotingCommand updateAndCreateTopic(ChannelHandlerContext ctx, Remoting final RemotingCommand response = RemotingCommand.createResponseCommand(null); final CreateTopicRequestHeader requestHeader = (CreateTopicRequestHeader) request.decodeCommandCustomHeader(CreateTopicRequestHeader.class); + log.info("updateAndCreateTopic called by {}", RemotingHelper.parseChannelRemoteAddr(ctx.channel())); + + // Topic名字是否与保留字段冲突 + if (requestHeader.getTopic().equals(this.brokerController.getBrokerConfig().getBrokerClusterName())) { + String errorMsg = + "the topic[" + requestHeader.getTopic() + "] is conflict with system reserved words."; + log.warn(errorMsg); + response.setCode(ResponseCode.SYSTEM_ERROR_VALUE); + response.setRemark(errorMsg); + return response; + } TopicConfig topicConfig = new TopicConfig(requestHeader.getTopic()); topicConfig.setReadQueueNums(requestHeader.getReadQueueNums()); @@ -153,6 +532,8 @@ private RemotingCommand deleteTopic(ChannelHandlerContext ctx, RemotingCommand r DeleteTopicRequestHeader requestHeader = (DeleteTopicRequestHeader) request.decodeCommandCustomHeader(DeleteTopicRequestHeader.class); + log.info("deleteTopic called by {}", RemotingHelper.parseChannelRemoteAddr(ctx.channel())); + this.brokerController.getTopicConfigManager().deleteTopicConfig(requestHeader.getTopic()); response.setCode(ResponseCode.SUCCESS_VALUE); @@ -167,7 +548,7 @@ private RemotingCommand getAllTopicConfig(ChannelHandlerContext ctx, RemotingCom final GetAllTopicConfigResponseHeader responseHeader = (GetAllTopicConfigResponseHeader) response.getCustomHeader(); - String content = this.brokerController.getTopicConfigManager().encodeIncludeSysTopic(); + String content = this.brokerController.getTopicConfigManager().encode(); if (content != null && content.length() > 0) { try { response.setBody(content.getBytes(MixAll.DEFAULT_CHARSET)); @@ -182,17 +563,11 @@ private RemotingCommand getAllTopicConfig(ChannelHandlerContext ctx, RemotingCom } else { log.error("No topic in this broker, client: " + ctx.channel().remoteAddress()); - response.setCode(ResponseCode.SYSTEM_ERROR_VALUE); response.setRemark("No topic in this broker"); return response; } - responseHeader.setVersion(brokerController.getTopicConfigManager().getCurrentDataVersion()); - responseHeader.setBrokerName(brokerController.getBrokerConfig().getBrokerName()); - responseHeader.setBrokerId(brokerController.getBrokerConfig().getBrokerId()); - responseHeader.setClusterName(brokerController.getBrokerConfig().getBrokerClusterName()); - response.setCode(ResponseCode.SUCCESS_VALUE); response.setRemark(null); @@ -203,6 +578,8 @@ private RemotingCommand getAllTopicConfig(ChannelHandlerContext ctx, RemotingCom private RemotingCommand updateBrokerConfig(ChannelHandlerContext ctx, RemotingCommand request) { final RemotingCommand response = RemotingCommand.createResponseCommand(null); + log.info("updateBrokerConfig called by {}", RemotingHelper.parseChannelRemoteAddr(ctx.channel())); + byte[] body = request.getBody(); if (body != null) { try { @@ -263,21 +640,15 @@ private RemotingCommand getBrokerConfig(ChannelHandlerContext ctx, RemotingComma } - private RemotingCommand getBrokerRuntimeInfo(ChannelHandlerContext ctx, RemotingCommand request) { - final RemotingCommand response = RemotingCommand.createResponseCommand(null); - - response.setCode(ResponseCode.SUCCESS_VALUE); - response.setRemark(null); - return response; - } - - private RemotingCommand searchOffsetByTimestamp(ChannelHandlerContext ctx, RemotingCommand request) throws RemotingCommandException { - final RemotingCommand response = RemotingCommand.createResponseCommand(SearchOffsetResponseHeader.class); - final SearchOffsetResponseHeader responseHeader = (SearchOffsetResponseHeader) response.getCustomHeader(); + final RemotingCommand response = + RemotingCommand.createResponseCommand(SearchOffsetResponseHeader.class); + final SearchOffsetResponseHeader responseHeader = + (SearchOffsetResponseHeader) response.getCustomHeader(); final SearchOffsetRequestHeader requestHeader = - (SearchOffsetRequestHeader) request.decodeCommandCustomHeader(SearchOffsetRequestHeader.class); + (SearchOffsetRequestHeader) request + .decodeCommandCustomHeader(SearchOffsetRequestHeader.class); long offset = this.brokerController.getMessageStore().getOffsetInQueueByTime(requestHeader.getTopic(), @@ -293,10 +664,13 @@ private RemotingCommand searchOffsetByTimestamp(ChannelHandlerContext ctx, Remot private RemotingCommand getMaxOffset(ChannelHandlerContext ctx, RemotingCommand request) throws RemotingCommandException { - final RemotingCommand response = RemotingCommand.createResponseCommand(GetMaxOffsetResponseHeader.class); - final GetMaxOffsetResponseHeader responseHeader = (GetMaxOffsetResponseHeader) response.getCustomHeader(); + final RemotingCommand response = + RemotingCommand.createResponseCommand(GetMaxOffsetResponseHeader.class); + final GetMaxOffsetResponseHeader responseHeader = + (GetMaxOffsetResponseHeader) response.getCustomHeader(); final GetMaxOffsetRequestHeader requestHeader = - (GetMaxOffsetRequestHeader) request.decodeCommandCustomHeader(GetMaxOffsetRequestHeader.class); + (GetMaxOffsetRequestHeader) request + .decodeCommandCustomHeader(GetMaxOffsetRequestHeader.class); long offset = this.brokerController.getMessageStore().getMaxOffsetInQuque(requestHeader.getTopic(), @@ -312,10 +686,13 @@ private RemotingCommand getMaxOffset(ChannelHandlerContext ctx, RemotingCommand private RemotingCommand getMinOffset(ChannelHandlerContext ctx, RemotingCommand request) throws RemotingCommandException { - final RemotingCommand response = RemotingCommand.createResponseCommand(GetMinOffsetResponseHeader.class); - final GetMinOffsetResponseHeader responseHeader = (GetMinOffsetResponseHeader) response.getCustomHeader(); + final RemotingCommand response = + RemotingCommand.createResponseCommand(GetMinOffsetResponseHeader.class); + final GetMinOffsetResponseHeader responseHeader = + (GetMinOffsetResponseHeader) response.getCustomHeader(); final GetMinOffsetRequestHeader requestHeader = - (GetMinOffsetRequestHeader) request.decodeCommandCustomHeader(GetMinOffsetRequestHeader.class); + (GetMinOffsetRequestHeader) request + .decodeCommandCustomHeader(GetMinOffsetRequestHeader.class); long offset = this.brokerController.getMessageStore().getMinOffsetInQuque(requestHeader.getTopic(), @@ -361,7 +738,7 @@ private RemotingCommand updateConsumerOffset(ChannelHandlerContext ctx, Remoting this.brokerController.getConsumerOffsetManager().commitOffset(requestHeader.getConsumerGroup(), requestHeader.getTopic(), requestHeader.getQueueId(), requestHeader.getCommitOffset()); - + UpdateCommitOffsetMoniter.printUpdatecommit(ctx.channel(), requestHeader); response.setCode(ResponseCode.SUCCESS_VALUE); response.setRemark(null); return response; @@ -379,19 +756,232 @@ private RemotingCommand queryConsumerOffset(ChannelHandlerContext ctx, RemotingC .decodeCommandCustomHeader(QueryConsumerOffsetRequestHeader.class); long offset = - this.brokerController.getConsumerOffsetManager().queryOffset(requestHeader.getConsumerGroup(), - requestHeader.getTopic(), requestHeader.getQueueId()); + this.brokerController.getConsumerOffsetManager().queryOffset( + requestHeader.getConsumerGroup(), requestHeader.getTopic(), requestHeader.getQueueId()); + // 订阅组存在 if (offset >= 0) { responseHeader.setOffset(offset); response.setCode(ResponseCode.SUCCESS_VALUE); response.setRemark(null); } + // 订阅组不存在 else { - response.setCode(MQResponseCode.QUERY_NOT_FOUND_VALUE); - response.setRemark("Not found, maybe this group consumer boot first"); + // 新版本服务器不做消费进度纠正 + if (request.getVersion() >= MQVersion.Version.V3_0_6_SNAPSHOT.ordinal()) { + response.setCode(MQResponseCode.QUERY_NOT_FOUND_VALUE); + response.setRemark("Not found, V3_0_6_SNAPSHOT maybe this group consumer boot first"); + } + + // TODO:以下流程待所有客户端都升级后,可以删除此段代码 + else { + long minOffset = + this.brokerController.getMessageStore().getMinOffsetInQuque(requestHeader.getTopic(), + requestHeader.getQueueId()); + long maxOffset = + this.brokerController.getMessageStore().getMaxOffsetInQuque(requestHeader.getTopic(), + requestHeader.getQueueId()); + + boolean consumeFromMinEnable = false; + if (0 == minOffset && maxOffset > 0) { + long minCommitLogOffset = + this.brokerController.getMessageStore().getCommitLogOffsetInQueue( + requestHeader.getTopic(), requestHeader.getQueueId(), minOffset); + long maxCommitLogOffset = + this.brokerController.getMessageStore().getCommitLogOffsetInQueue( + requestHeader.getTopic(), requestHeader.getQueueId(), maxOffset - 1); + + long memorySpan = + (long) (StoreUtil.TotalPhysicalMemorySize * (this.brokerController + .getMessageStoreConfig().getAccessMessageInMemoryMaxRatio() / 100.0)); + + long diff = maxCommitLogOffset - minCommitLogOffset; + if (diff < memorySpan) { + consumeFromMinEnable = true; + log.info( + "the consumer group[{}] first subscribed, minOffset: {} maxOffset: {}, from min.",// + requestHeader.getConsumerGroup(),// + minOffset,// + maxOffset); + } + } + else if (minOffset > 0 && maxOffset > 0) { + consumeFromMinEnable = false; + } + else { + consumeFromMinEnable = true; + log.info( + "the consumer group[{}] first subscribed, minOffset: {} maxOffset: {}, from min, and unknow offset.",// + requestHeader.getConsumerGroup(),// + minOffset,// + maxOffset); + } + + // 说明这个队列在服务器存储的消息比较少或者没有消息 + // 订阅组消费进度不存在情况下,从0开始消费 + if (consumeFromMinEnable) { + responseHeader.setOffset(0L); + response.setCode(ResponseCode.SUCCESS_VALUE); + response.setRemark(null); + } + else { + response.setCode(MQResponseCode.QUERY_NOT_FOUND_VALUE); + response.setRemark("Not found, maybe this group consumer boot first"); + } + } } return response; } + + + private HashMap prepareRuntimeInfo() { + HashMap runtimeInfo = this.brokerController.getMessageStore().getRuntimeInfo(); + runtimeInfo.put("brokerVersionDesc", MQVersion.getVersionDesc(MQVersion.CurrentVersion)); + runtimeInfo.put("brokerVersion", String.valueOf(MQVersion.CurrentVersion)); + + runtimeInfo.put("msgPutTotalYesterdayMorning", + String.valueOf(this.brokerController.getBrokerStats().getMsgPutTotalYesterdayMorning())); + runtimeInfo.put("msgPutTotalTodayMorning", + String.valueOf(this.brokerController.getBrokerStats().getMsgPutTotalTodayMorning())); + runtimeInfo.put("msgPutTotalTodayNow", + String.valueOf(this.brokerController.getBrokerStats().getMsgPutTotalTodayNow())); + + runtimeInfo.put("msgGetTotalYesterdayMorning", + String.valueOf(this.brokerController.getBrokerStats().getMsgGetTotalYesterdayMorning())); + runtimeInfo.put("msgGetTotalTodayMorning", + String.valueOf(this.brokerController.getBrokerStats().getMsgGetTotalTodayMorning())); + runtimeInfo.put("msgGetTotalTodayNow", + String.valueOf(this.brokerController.getBrokerStats().getMsgGetTotalTodayNow())); + + runtimeInfo.put("sendThreadPoolQueueSize", + String.valueOf(this.brokerController.getSendThreadPoolQueue().size())); + + runtimeInfo.put("sendThreadPoolQueueCapacity", + String.valueOf(this.brokerController.getBrokerConfig().getSendThreadPoolQueueCapacity())); + + return runtimeInfo; + } + + + private RemotingCommand getBrokerRuntimeInfo(ChannelHandlerContext ctx, RemotingCommand request) { + final RemotingCommand response = RemotingCommand.createResponseCommand(null); + + HashMap runtimeInfo = this.prepareRuntimeInfo(); + KVTable kvTable = new KVTable(); + kvTable.setTable(runtimeInfo); + + byte[] body = kvTable.encode(); + response.setBody(body); + response.setCode(ResponseCode.SUCCESS_VALUE); + response.setRemark(null); + return response; + } + + + private RemotingCommand getAllConsumerOffset(ChannelHandlerContext ctx, RemotingCommand request) { + final RemotingCommand response = RemotingCommand.createResponseCommand(null); + + String content = this.brokerController.getConsumerOffsetManager().encode(); + if (content != null && content.length() > 0) { + try { + response.setBody(content.getBytes(MixAll.DEFAULT_CHARSET)); + } + catch (UnsupportedEncodingException e) { + log.error("get all consumer offset from master error.", e); + + response.setCode(ResponseCode.SYSTEM_ERROR_VALUE); + response.setRemark("UnsupportedEncodingException " + e); + return response; + } + } + else { + log.error("No consumer offset in this broker, client: " + ctx.channel().remoteAddress()); + response.setCode(ResponseCode.SYSTEM_ERROR_VALUE); + response.setRemark("No consumer offset in this broker"); + return response; + } + + response.setCode(ResponseCode.SUCCESS_VALUE); + response.setRemark(null); + + return response; + } + + + private RemotingCommand getAllDelayOffset(ChannelHandlerContext ctx, RemotingCommand request) { + final RemotingCommand response = RemotingCommand.createResponseCommand(null); + + String content = + ((DefaultMessageStore) this.brokerController.getMessageStore()).getScheduleMessageService() + .encode(); + if (content != null && content.length() > 0) { + try { + response.setBody(content.getBytes(MixAll.DEFAULT_CHARSET)); + } + catch (UnsupportedEncodingException e) { + log.error("get all delay offset from master error.", e); + + response.setCode(ResponseCode.SYSTEM_ERROR_VALUE); + response.setRemark("UnsupportedEncodingException " + e); + return response; + } + } + else { + log.error("No delay offset in this broker, client: " + ctx.channel().remoteAddress()); + response.setCode(ResponseCode.SYSTEM_ERROR_VALUE); + response.setRemark("No delay offset in this broker"); + return response; + } + + response.setCode(ResponseCode.SUCCESS_VALUE); + response.setRemark(null); + + return response; + } + + + private RemotingCommand deleteSubscriptionGroup(ChannelHandlerContext ctx, RemotingCommand request) + throws RemotingCommandException { + final RemotingCommand response = RemotingCommand.createResponseCommand(null); + DeleteSubscriptionGroupRequestHeader requestHeader = + (DeleteSubscriptionGroupRequestHeader) request + .decodeCommandCustomHeader(DeleteSubscriptionGroupRequestHeader.class); + + log.info("deleteSubscriptionGroup called by {}", RemotingHelper.parseChannelRemoteAddr(ctx.channel())); + + this.brokerController.getSubscriptionGroupManager().deleteSubscriptionGroupConfig( + requestHeader.getGroupName()); + + response.setCode(ResponseCode.SUCCESS_VALUE); + response.setRemark(null); + return response; + } + + + public RemotingCommand resetOffset(ChannelHandlerContext ctx, RemotingCommand request) + throws RemotingCommandException { + final ResetOffsetRequestHeader requestHeader = + (ResetOffsetRequestHeader) request.decodeCommandCustomHeader(ResetOffsetRequestHeader.class); + log.info("[reset-offset] reset offset started by {}. topic={}, group={}, timestamp={}, isForce={}", + new Object[] { RemotingHelper.parseChannelRemoteAddr(ctx.channel()), requestHeader.getTopic(), + requestHeader.getGroup(), requestHeader.getTimestamp(), requestHeader.isForce() }); + return this.brokerController.getBroker2Client().resetOffset(requestHeader.getTopic(), + requestHeader.getGroup(), requestHeader.getTimestamp(), requestHeader.isForce()); + } + + + public RemotingCommand getConsumerStatus(ChannelHandlerContext ctx, RemotingCommand request) + throws RemotingCommandException { + final GetConsumerStatusRequestHeader requestHeader = + (GetConsumerStatusRequestHeader) request + .decodeCommandCustomHeader(GetConsumerStatusRequestHeader.class); + + log.info("get consumer status by {}. topic={}, group={}", + new Object[] { RemotingHelper.parseChannelRemoteAddr(ctx.channel()), requestHeader.getTopic(), + requestHeader.getGroup() }); + + return this.brokerController.getBroker2Client().getConsumeStatus(requestHeader.getTopic(), + requestHeader.getGroup(), requestHeader.getClientAddr()); + } } diff --git a/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/processor/ClientManageProcessor.java b/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/processor/ClientManageProcessor.java index f763f8df..39e14244 100644 --- a/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/processor/ClientManageProcessor.java +++ b/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/processor/ClientManageProcessor.java @@ -1,40 +1,58 @@ /** - * $Id: ClientManageProcessor.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.broker.processor; import io.netty.channel.ChannelHandlerContext; +import java.util.List; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.alibaba.rocketmq.broker.BrokerController; import com.alibaba.rocketmq.broker.client.ClientChannelInfo; +import com.alibaba.rocketmq.broker.client.ConsumerGroupInfo; import com.alibaba.rocketmq.common.MixAll; +import com.alibaba.rocketmq.common.constant.LoggerName; +import com.alibaba.rocketmq.common.constant.PermName; import com.alibaba.rocketmq.common.protocol.MQProtos.MQRequestCode; -import com.alibaba.rocketmq.common.protocol.header.SendMessageRequestHeader; -import com.alibaba.rocketmq.common.protocol.header.SendMessageResponseHeader; +import com.alibaba.rocketmq.common.protocol.header.GetConsumerListByGroupRequestHeader; +import com.alibaba.rocketmq.common.protocol.header.GetConsumerListByGroupResponseBody; +import com.alibaba.rocketmq.common.protocol.header.GetConsumerListByGroupResponseHeader; import com.alibaba.rocketmq.common.protocol.header.UnregisterClientRequestHeader; import com.alibaba.rocketmq.common.protocol.header.UnregisterClientResponseHeader; import com.alibaba.rocketmq.common.protocol.heartbeat.ConsumerData; import com.alibaba.rocketmq.common.protocol.heartbeat.HeartbeatData; import com.alibaba.rocketmq.common.protocol.heartbeat.ProducerData; +import com.alibaba.rocketmq.common.subscription.SubscriptionGroupConfig; import com.alibaba.rocketmq.remoting.common.RemotingHelper; import com.alibaba.rocketmq.remoting.exception.RemotingCommandException; import com.alibaba.rocketmq.remoting.netty.NettyRequestProcessor; import com.alibaba.rocketmq.remoting.protocol.RemotingCommand; import com.alibaba.rocketmq.remoting.protocol.RemotingProtos.ResponseCode; -import com.google.protobuf.InvalidProtocolBufferException; /** - * Clientעע - * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * Client注册与注销管理 * + * @author shijia.wxr + * @since 2013-7-26 */ public class ClientManageProcessor implements NettyRequestProcessor { - private static final Logger log = LoggerFactory.getLogger(MixAll.BrokerLoggerName); + private static final Logger log = LoggerFactory.getLogger(LoggerName.BrokerLoggerName); private final BrokerController brokerController; @@ -53,6 +71,8 @@ public RemotingCommand processRequest(ChannelHandlerContext ctx, RemotingCommand return this.heartBeat(ctx, request); case UNREGISTER_CLIENT: return this.unregisterClient(ctx, request); + case GET_CONSUMER_LIST_BY_GROUP: + return this.getConsumerListByGroup(ctx, request); default: break; } @@ -60,12 +80,47 @@ public RemotingCommand processRequest(ChannelHandlerContext ctx, RemotingCommand } + public RemotingCommand getConsumerListByGroup(ChannelHandlerContext ctx, RemotingCommand request) + throws RemotingCommandException { + final RemotingCommand response = + RemotingCommand.createResponseCommand(GetConsumerListByGroupResponseHeader.class); + final GetConsumerListByGroupRequestHeader requestHeader = + (GetConsumerListByGroupRequestHeader) request + .decodeCommandCustomHeader(GetConsumerListByGroupRequestHeader.class); + + ConsumerGroupInfo consumerGroupInfo = + this.brokerController.getConsumerManager().getConsumerGroupInfo( + requestHeader.getConsumerGroup()); + if (consumerGroupInfo != null) { + List clientIds = consumerGroupInfo.getAllClientId(); + if (!clientIds.isEmpty()) { + GetConsumerListByGroupResponseBody body = new GetConsumerListByGroupResponseBody(); + body.setConsumerIdList(clientIds); + response.setBody(body.encode()); + response.setCode(ResponseCode.SUCCESS_VALUE); + response.setRemark(null); + return response; + } + else { + log.warn("getAllClientId failed, {} {}", requestHeader.getConsumerGroup(), + RemotingHelper.parseChannelRemoteAddr(ctx.channel())); + } + } + else { + log.warn("getConsumerGroupInfo failed, {} {}", requestHeader.getConsumerGroup(), + RemotingHelper.parseChannelRemoteAddr(ctx.channel())); + } + + response.setCode(ResponseCode.SYSTEM_ERROR_VALUE); + response.setRemark("no consumer for this group, " + requestHeader.getConsumerGroup()); + return response; + } + + public RemotingCommand unregisterClient(ChannelHandlerContext ctx, RemotingCommand request) throws RemotingCommandException { final RemotingCommand response = RemotingCommand.createResponseCommand(UnregisterClientResponseHeader.class); - final UnregisterClientResponseHeader responseHeader = - (UnregisterClientResponseHeader) response.getCustomHeader(); final UnregisterClientRequestHeader requestHeader = (UnregisterClientRequestHeader) request .decodeCommandCustomHeader(UnregisterClientRequestHeader.class); @@ -77,13 +132,13 @@ public RemotingCommand unregisterClient(ChannelHandlerContext ctx, RemotingComma request.getVersion()// ); - // עProducer + // 注销Producer final String producerGroup = requestHeader.getProducerGroup(); if (producerGroup != null) { this.brokerController.getProducerManager().unregisterProducer(producerGroup, clientChannelInfo); } - // עConsumer + // 注销Consumer final String consumerGroup = requestHeader.getProducerGroup(); if (consumerGroup != null) { this.brokerController.getConsumerManager().unregisterConsumer(consumerGroup, clientChannelInfo); @@ -97,17 +152,8 @@ public RemotingCommand unregisterClient(ChannelHandlerContext ctx, RemotingComma public RemotingCommand heartBeat(ChannelHandlerContext ctx, RemotingCommand request) { RemotingCommand response = RemotingCommand.createResponseCommand(null); - HeartbeatData heartbeatData = null; - try { - heartbeatData = HeartbeatData.decode(request.getBody()); - } - catch (InvalidProtocolBufferException e) { - log.error("decode heartbeat body from channel[{}] error", - RemotingHelper.parseChannelRemoteAddr(ctx.channel())); - response.setCode(ResponseCode.SYSTEM_ERROR_VALUE); - response.setRemark("decode heartbeat body error"); - return response; - } + + HeartbeatData heartbeatData = HeartbeatData.decode(request.getBody(), HeartbeatData.class); ClientChannelInfo clientChannelInfo = new ClientChannelInfo(// ctx.channel(),// @@ -116,20 +162,40 @@ public RemotingCommand heartBeat(ChannelHandlerContext ctx, RemotingCommand requ request.getVersion()// ); - // עConsumer + // 注册Consumer for (ConsumerData data : heartbeatData.getConsumerDataSet()) { - this.brokerController.getConsumerManager().registerConsumer(// + SubscriptionGroupConfig subscriptionGroupConfig = + this.brokerController.getSubscriptionGroupManager().findSubscriptionGroupConfig( + data.getGroupName()); + if (null != subscriptionGroupConfig) { + String newTopic = MixAll.getRetryTopic(data.getGroupName()); + this.brokerController.getTopicConfigManager().createTopicInSendMessageBackMethod(// + newTopic,// + subscriptionGroupConfig.getRetryQueueNums(), // + PermName.PERM_WRITE | PermName.PERM_READ); + } + + boolean changed = this.brokerController.getConsumerManager().registerConsumer(// data.getGroupName(),// clientChannelInfo,// data.getConsumeType(),// data.getMessageModel(),// + data.getConsumeFromWhere(),// data.getSubscriptionDataSet()// ); + + if (changed) { + log.info("registerConsumer info changed {} {}",// + data.toString(),// + RemotingHelper.parseChannelRemoteAddr(ctx.channel())// + ); + } } - // עProducer + // 注册Producer for (ProducerData data : heartbeatData.getProducerDataSet()) { - this.brokerController.getProducerManager().registerProducer(data.getGroupName(), clientChannelInfo); + this.brokerController.getProducerManager().registerProducer(data.getGroupName(), + clientChannelInfo); } response.setCode(ResponseCode.SUCCESS_VALUE); diff --git a/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/processor/EndTransactionProcessor.java b/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/processor/EndTransactionProcessor.java index e2e1e003..8141280b 100644 --- a/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/processor/EndTransactionProcessor.java +++ b/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/processor/EndTransactionProcessor.java @@ -1,5 +1,17 @@ /** - * $Id: EndTransactionProcessor.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.broker.processor; @@ -9,14 +21,15 @@ import org.slf4j.LoggerFactory; import com.alibaba.rocketmq.broker.BrokerController; -import com.alibaba.rocketmq.common.Message; -import com.alibaba.rocketmq.common.MessageDecoder; -import com.alibaba.rocketmq.common.MessageExt; -import com.alibaba.rocketmq.common.MixAll; import com.alibaba.rocketmq.common.TopicFilterType; +import com.alibaba.rocketmq.common.constant.LoggerName; +import com.alibaba.rocketmq.common.message.MessageConst; +import com.alibaba.rocketmq.common.message.MessageDecoder; +import com.alibaba.rocketmq.common.message.MessageExt; import com.alibaba.rocketmq.common.protocol.MQProtos.MQResponseCode; import com.alibaba.rocketmq.common.protocol.header.EndTransactionRequestHeader; import com.alibaba.rocketmq.common.sysflag.MessageSysFlag; +import com.alibaba.rocketmq.remoting.common.RemotingHelper; import com.alibaba.rocketmq.remoting.exception.RemotingCommandException; import com.alibaba.rocketmq.remoting.netty.NettyRequestProcessor; import com.alibaba.rocketmq.remoting.protocol.RemotingCommand; @@ -24,17 +37,16 @@ import com.alibaba.rocketmq.store.MessageExtBrokerInner; import com.alibaba.rocketmq.store.MessageStore; import com.alibaba.rocketmq.store.PutMessageResult; -import com.alibaba.rocketmq.store.SelectMapedBufferResult; /** - * CommitRollback - * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * Commit或Rollback事务 * + * @author shijia.wxr + * @since 2013-7-26 */ public class EndTransactionProcessor implements NettyRequestProcessor { - private static final Logger log = LoggerFactory.getLogger(MixAll.BrokerLoggerName); + private static final Logger log = LoggerFactory.getLogger(LoggerName.BrokerLoggerName); private final BrokerController brokerController; @@ -64,7 +76,7 @@ private MessageExtBrokerInner endMessageTransaction(MessageExt msgExt) { msgInner.setReconsumeTimes(msgExt.getReconsumeTimes()); msgInner.setWaitStoreMsgOK(false); - msgInner.clearProperty(Message.PROPERTY_DELAY_TIME_LEVEL); + msgInner.clearProperty(MessageConst.PROPERTY_DELAY_TIME_LEVEL); msgInner.setTopic(msgExt.getTopic()); msgInner.setQueueId(msgExt.getQueueId()); @@ -72,33 +84,106 @@ private MessageExtBrokerInner endMessageTransaction(MessageExt msgExt) { return msgInner; } + private static final Logger logTransaction = LoggerFactory.getLogger(LoggerName.TransactionLoggerName); + @Override public RemotingCommand processRequest(ChannelHandlerContext ctx, RemotingCommand request) throws RemotingCommandException { final RemotingCommand response = RemotingCommand.createResponseCommand(null); final EndTransactionRequestHeader requestHeader = - (EndTransactionRequestHeader) request.decodeCommandCustomHeader(EndTransactionRequestHeader.class); + (EndTransactionRequestHeader) request + .decodeCommandCustomHeader(EndTransactionRequestHeader.class); + + // 回查应答 + if (requestHeader.getFromTransactionCheck()) { + switch (requestHeader.getCommitOrRollback()) { + // 不提交也不回滚 + case MessageSysFlag.TransactionNotType: { + logTransaction.warn("check producer[{}] transaction state, but it's pending status.\n"// + + "RequestHeader: {} Remark: {}",// + RemotingHelper.parseChannelRemoteAddr(ctx.channel()), // + requestHeader.toString(),// + request.getRemark()); + return null; + } + // 提交 + case MessageSysFlag.TransactionCommitType: { + logTransaction.warn( + "check producer[{}] transaction state, the producer commit the message.\n"// + + "RequestHeader: {} Remark: {}",// + RemotingHelper.parseChannelRemoteAddr(ctx.channel()), // + requestHeader.toString(),// + request.getRemark()); + + break; + } + // 回滚 + case MessageSysFlag.TransactionRollbackType: { + logTransaction.warn( + "check producer[{}] transaction state, the producer rollback the message.\n"// + + "RequestHeader: {} Remark: {}",// + RemotingHelper.parseChannelRemoteAddr(ctx.channel()), // + requestHeader.toString(),// + request.getRemark()); + break; + } + default: + return null; + } + } + // 正常提交回滚 + else { + switch (requestHeader.getCommitOrRollback()) { + // 不提交也不回滚 + case MessageSysFlag.TransactionNotType: { + logTransaction.warn( + "the producer[{}] end transaction in sending message, and it's pending status.\n"// + + "RequestHeader: {} Remark: {}",// + RemotingHelper.parseChannelRemoteAddr(ctx.channel()), // + requestHeader.toString(),// + request.getRemark()); + return null; + } + // 提交 + case MessageSysFlag.TransactionCommitType: { + break; + } + // 回滚 + case MessageSysFlag.TransactionRollbackType: { + logTransaction.warn( + "the producer[{}] end transaction in sending message, rollback the message.\n"// + + "RequestHeader: {} Remark: {}",// + RemotingHelper.parseChannelRemoteAddr(ctx.channel()), // + requestHeader.toString(),// + request.getRemark()); + break; + } + default: + return null; + } + } final MessageExt msgExt = - this.brokerController.getMessageStore().lookMessageByOffset(requestHeader.getCommitLogOffset()); + this.brokerController.getMessageStore().lookMessageByOffset( + requestHeader.getCommitLogOffset()); if (msgExt != null) { - // УProducer Group - final String pgroupRead = msgExt.getProperty(Message.PROPERTY_PRODUCER_GROUP); + // 校验Producer Group + final String pgroupRead = msgExt.getProperty(MessageConst.PROPERTY_PRODUCER_GROUP); if (!pgroupRead.equals(requestHeader.getProducerGroup())) { response.setCode(ResponseCode.SYSTEM_ERROR_VALUE); response.setRemark("the producer group wrong"); return response; } - // УTransaction State Table Offset + // 校验Transaction State Table Offset if (msgExt.getQueueOffset() != requestHeader.getTranStateTableOffset()) { response.setCode(ResponseCode.SYSTEM_ERROR_VALUE); response.setRemark("the transaction state table offset wrong"); return response; } - // УCommit Log Offset + // 校验Commit Log Offset if (msgExt.getCommitLogOffset() != requestHeader.getCommitLogOffset()) { response.setCode(ResponseCode.SYSTEM_ERROR_VALUE); response.setRemark("the commit log offset wrong"); diff --git a/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/processor/ForwardRequestProcessor.java b/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/processor/ForwardRequestProcessor.java index 851806c3..226ede0e 100644 --- a/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/processor/ForwardRequestProcessor.java +++ b/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/processor/ForwardRequestProcessor.java @@ -1,5 +1,17 @@ /** - * $Id: ForwardRequestProcessor.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.broker.processor; @@ -9,19 +21,19 @@ import org.slf4j.LoggerFactory; import com.alibaba.rocketmq.broker.BrokerController; -import com.alibaba.rocketmq.common.MixAll; +import com.alibaba.rocketmq.common.constant.LoggerName; import com.alibaba.rocketmq.remoting.netty.NettyRequestProcessor; import com.alibaba.rocketmq.remoting.protocol.RemotingCommand; /** - * ClientתͨڹءͳĿ - * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * 向Client转发请求,通常用于管理、监控、统计目的 * + * @author shijia.wxr + * @since 2013-7-26 */ public class ForwardRequestProcessor implements NettyRequestProcessor { - private static final Logger log = LoggerFactory.getLogger(MixAll.BrokerLoggerName); + private static final Logger log = LoggerFactory.getLogger(LoggerName.BrokerLoggerName); private final BrokerController brokerController; diff --git a/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/processor/PullMessageProcessor.java b/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/processor/PullMessageProcessor.java index 7a0c057d..d9fb98fc 100644 --- a/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/processor/PullMessageProcessor.java +++ b/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/processor/PullMessageProcessor.java @@ -1,5 +1,17 @@ /** - * $Id: PullMessageProcessor.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.broker.processor; @@ -13,29 +25,39 @@ import org.slf4j.LoggerFactory; import com.alibaba.rocketmq.broker.BrokerController; +import com.alibaba.rocketmq.broker.client.ConsumerGroupInfo; +import com.alibaba.rocketmq.broker.digestlog.PullmsgLiveMoniter; import com.alibaba.rocketmq.broker.longpolling.PullRequest; import com.alibaba.rocketmq.broker.pagecache.ManyMessageTransfer; -import com.alibaba.rocketmq.common.MixAll; import com.alibaba.rocketmq.common.TopicConfig; +import com.alibaba.rocketmq.common.constant.LoggerName; +import com.alibaba.rocketmq.common.constant.PermName; +import com.alibaba.rocketmq.common.filter.FilterAPI; +import com.alibaba.rocketmq.common.help.FAQUrl; import com.alibaba.rocketmq.common.protocol.MQProtos.MQResponseCode; import com.alibaba.rocketmq.common.protocol.header.PullMessageRequestHeader; import com.alibaba.rocketmq.common.protocol.header.PullMessageResponseHeader; +import com.alibaba.rocketmq.common.protocol.heartbeat.MessageModel; +import com.alibaba.rocketmq.common.protocol.heartbeat.SubscriptionData; +import com.alibaba.rocketmq.common.subscription.SubscriptionGroupConfig; import com.alibaba.rocketmq.common.sysflag.PullSysFlag; +import com.alibaba.rocketmq.remoting.common.RemotingHelper; import com.alibaba.rocketmq.remoting.exception.RemotingCommandException; import com.alibaba.rocketmq.remoting.netty.NettyRequestProcessor; import com.alibaba.rocketmq.remoting.protocol.RemotingCommand; import com.alibaba.rocketmq.remoting.protocol.RemotingProtos.ResponseCode; import com.alibaba.rocketmq.store.GetMessageResult; +import com.alibaba.rocketmq.store.config.BrokerRole; /** - * Ϣ - * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * 拉消息请求处理 * + * @author shijia.wxr + * @since 2013-7-26 */ public class PullMessageProcessor implements NettyRequestProcessor { - private static final Logger log = LoggerFactory.getLogger(MixAll.BrokerLoggerName); + private static final Logger log = LoggerFactory.getLogger(LoggerName.BrokerLoggerName); private final BrokerController brokerController; @@ -54,81 +76,118 @@ public RemotingCommand processRequest(final ChannelHandlerContext ctx, RemotingC public void excuteRequestWhenWakeup(final Channel channel, final RemotingCommand request) throws RemotingCommandException { - final RemotingCommand response = this.processRequest(channel, request, false); - if (response != null) { - response.setOpaque(request.getOpaque()); - response.markResponseType(); - try { - channel.write(response).addListener(new ChannelFutureListener() { - @Override - public void operationComplete(ChannelFuture future) throws Exception { - if (!future.isSuccess()) { - log.error("processRequestWrapper response to " + future.channel().remoteAddress() - + " failed", future.cause()); + Runnable run = new Runnable() { + @Override + public void run() { + try { + final RemotingCommand response = + PullMessageProcessor.this.processRequest(channel, request, false); + + if (response != null) { + response.setOpaque(request.getOpaque()); + response.markResponseType(); + try { + channel.writeAndFlush(response).addListener(new ChannelFutureListener() { + @Override + public void operationComplete(ChannelFuture future) throws Exception { + if (!future.isSuccess()) { + log.error("processRequestWrapper response to " + + future.channel().remoteAddress() + " failed", + future.cause()); + log.error(request.toString()); + log.error(response.toString()); + } + } + }); + } + catch (Throwable e) { + log.error("processRequestWrapper process request over, but response failed", e); log.error(request.toString()); log.error(response.toString()); } } - }); - } - catch (Throwable e) { - log.error("processRequestWrapper process request over, but response failed", e); - log.error(request.toString()); - log.error(response.toString()); + } + catch (RemotingCommandException e1) { + log.error("excuteRequestWhenWakeup run", e1); + } } - } + }; + + this.brokerController.getPullMessageExecutor().submit(run); } private RemotingCommand processRequest(final Channel channel, RemotingCommand request, boolean brokerAllowSuspend) throws RemotingCommandException { RemotingCommand response = RemotingCommand.createResponseCommand(PullMessageResponseHeader.class); - final PullMessageResponseHeader responseHeader = (PullMessageResponseHeader) response.getCustomHeader(); + final PullMessageResponseHeader responseHeader = + (PullMessageResponseHeader) response.getCustomHeader(); final PullMessageRequestHeader requestHeader = (PullMessageRequestHeader) request.decodeCommandCustomHeader(PullMessageRequestHeader.class); - // ʹsendfileԱҪ + // 由于使用sendfile,所以必须要设置 response.setOpaque(request.getOpaque()); if (log.isDebugEnabled()) { log.debug("receive PullMessage request command, " + request); } - // BrokerȨ - if (!MixAll.isReadable(this.brokerController.getBrokerConfig().getBrokerPermission())) { + // 检查Broker权限 + if (!PermName.isReadable(this.brokerController.getBrokerConfig().getBrokerPermission())) { response.setCode(MQResponseCode.NO_PERMISSION_VALUE); response.setRemark("the broker[" + this.brokerController.getBrokerConfig().getBrokerIP1() + "] pulling message is forbidden"); return response; } + // 确保订阅组存在 + SubscriptionGroupConfig subscriptionGroupConfig = + this.brokerController.getSubscriptionGroupManager().findSubscriptionGroupConfig( + requestHeader.getConsumerGroup()); + if (null == subscriptionGroupConfig) { + response.setCode(MQResponseCode.SUBSCRIPTION_GROUP_NOT_EXIST_VALUE); + response.setRemark("subscription group not exist, " + requestHeader.getConsumerGroup() + " " + + FAQUrl.suggestTodo(FAQUrl.SUBSCRIPTION_GROUP_NOT_EXIST)); + return response; + } + + // 这个订阅组是否可以消费消息 + if (!subscriptionGroupConfig.isConsumeEnable()) { + response.setCode(MQResponseCode.NO_PERMISSION_VALUE); + response.setRemark("subscription group no permission, " + requestHeader.getConsumerGroup()); + return response; + } + final boolean hasSuspendFlag = PullSysFlag.hasSuspendFlag(requestHeader.getSysFlag()); final boolean hasCommitOffsetFlag = PullSysFlag.hasCommitOffsetFlag(requestHeader.getSysFlag()); final boolean hasSubscriptionFlag = PullSysFlag.hasSubscriptionFlag(requestHeader.getSysFlag()); final long suspendTimeoutMillisLong = hasSuspendFlag ? requestHeader.getSuspendTimeoutMillis() : 0; - // topicǷ + // 检查topic是否存在 TopicConfig topicConfig = this.brokerController.getTopicConfigManager().selectTopicConfig(requestHeader.getTopic()); if (null == topicConfig) { - log.error("the topic " + requestHeader.getTopic() + " not exist, producer: " + channel.remoteAddress()); + log.error("the topic " + requestHeader.getTopic() + " not exist, consumer: " + + RemotingHelper.parseChannelRemoteAddr(channel)); response.setCode(MQResponseCode.TOPIC_NOT_EXIST_VALUE); - response.setRemark("topic not exist, apply first please!"); + response.setRemark("topic[" + requestHeader.getTopic() + "] not exist, apply first please!" + + FAQUrl.suggestTodo(FAQUrl.APPLY_TOPIC_URL)); return response; } - // topicȨ - if (!MixAll.isReadable(topicConfig.getPerm())) { + // 检查topic权限 + if (!PermName.isReadable(topicConfig.getPerm())) { response.setCode(MQResponseCode.NO_PERMISSION_VALUE); response.setRemark("the topic[" + requestHeader.getTopic() + "] pulling message is forbidden"); return response; } - // Ч + // 检查队列有效性 if (requestHeader.getQueueId() < 0 || requestHeader.getQueueId() >= topicConfig.getReadQueueNums()) { String errorInfo = - "queueId[" + requestHeader.getQueueId() + "] is illagal, topicConfig.readQueueNums: " + "queueId[" + requestHeader.getQueueId() + "] is illagal,Topic :" + + requestHeader.getTopic() + " topicConfig.readQueueNums: " + topicConfig.getReadQueueNums() + " consumer: " + channel.remoteAddress(); log.warn(errorInfo); response.setCode(ResponseCode.SYSTEM_ERROR_VALUE); @@ -136,18 +195,86 @@ private RemotingCommand processRequest(final Channel channel, RemotingCommand re return response; } + // 订阅关系处理 + SubscriptionData subscriptionData = null; + if (hasSubscriptionFlag) { + try { + subscriptionData = + FilterAPI.buildSubscriptionData(requestHeader.getTopic(), + requestHeader.getSubscription()); + } + catch (Exception e) { + log.warn("parse the consumer's subscription[{}] failed, group: {}", + requestHeader.getSubscription(),// + requestHeader.getConsumerGroup()); + response.setCode(MQResponseCode.SUBSCRIPTION_PARSE_FAILED_VALUE); + response.setRemark("parse the consumer's subscription failed"); + return response; + } + } + else { + ConsumerGroupInfo consumerGroupInfo = + this.brokerController.getConsumerManager().getConsumerGroupInfo( + requestHeader.getConsumerGroup()); + if (null == consumerGroupInfo) { + log.warn("the consumer's group info not exist, group: {}", requestHeader.getConsumerGroup()); + response.setCode(MQResponseCode.SUBSCRIPTION_NOT_EXIST_VALUE); + response.setRemark("the consumer's group info not exist" + + FAQUrl.suggestTodo(FAQUrl.SAME_GROUP_DIFFERENT_TOPIC)); + return response; + } + + if (!subscriptionGroupConfig.isConsumeBroadcastEnable() // + && consumerGroupInfo.getMessageModel() == MessageModel.BROADCASTING) { + response.setCode(MQResponseCode.NO_PERMISSION_VALUE); + response.setRemark("the consumer group[" + requestHeader.getConsumerGroup() + + "] can not consume by broadcast way"); + return response; + } + + subscriptionData = consumerGroupInfo.findSubscriptionData(requestHeader.getTopic()); + if (null == subscriptionData) { + log.warn("the consumer's subscription not exist, group: {}", requestHeader.getConsumerGroup()); + response.setCode(MQResponseCode.SUBSCRIPTION_NOT_EXIST_VALUE); + response.setRemark("the consumer's subscription not exist" + + FAQUrl.suggestTodo(FAQUrl.SAME_GROUP_DIFFERENT_TOPIC)); + return response; + } + + // 判断Broker的订阅关系版本是否最新 + if (subscriptionData.getSubVersion() < requestHeader.getSubVersion()) { + log.warn("the broker's subscription is not latest, group: {} {}", + requestHeader.getConsumerGroup(), subscriptionData.getSubString()); + response.setCode(MQResponseCode.SUBSCRIPTION_NOT_LATEST_VALUE); + response.setRemark("the consumer's subscription not latest"); + return response; + } + } + final GetMessageResult getMessageResult = this.brokerController.getMessageStore().getMessage(requestHeader.getTopic(), - requestHeader.getQueueId(), requestHeader.getQueueOffset(), requestHeader.getMaxMsgNums(), - null); + requestHeader.getQueueId(), requestHeader.getQueueOffset(), + requestHeader.getMaxMsgNums(), subscriptionData); + if (getMessageResult != null) { + if (getMessageResult.getBufferTotalSize() > 0) { + PullmsgLiveMoniter.printProcessRequestLive(channel, request, getMessageResult); + } response.setRemark(getMessageResult.getStatus().name()); - responseHeader.setNextBeginOffset(getMessageResult.getNextBeginOffset()); - responseHeader.setSuggestPullingFromSlave(getMessageResult.isSuggestPullingFromSlave()); responseHeader.setMinOffset(getMessageResult.getMinOffset()); responseHeader.setMaxOffset(getMessageResult.getMaxOffset()); + // 消费较慢,重定向到另外一台机器 + if (getMessageResult.isSuggestPullingFromSlave()) { + responseHeader.setSuggestWhichBrokerId(subscriptionGroupConfig + .getWhichBrokerWhenConsumeSlowly()); + } + // 消费正常,按照订阅组配置重定向 + else { + responseHeader.setSuggestWhichBrokerId(subscriptionGroupConfig.getBrokerId()); + } + switch (getMessageResult.getStatus()) { case FOUND: response.setCode(ResponseCode.SUCCESS_VALUE); @@ -155,10 +282,24 @@ private RemotingCommand processRequest(final Channel channel, RemotingCommand re case MESSAGE_WAS_REMOVING: response.setCode(MQResponseCode.PULL_RETRY_IMMEDIATELY_VALUE); break; - // ֵʾʱûУӦ̽ͻOffsetΪ0 + // 这两个返回值都表示服务器暂时没有这个队列,应该立刻将客户端Offset重置为0 case NO_MATCHED_LOGIC_QUEUE: case NO_MESSAGE_IN_QUEUE: - response.setCode(MQResponseCode.PULL_NOT_FOUND_VALUE); + if (0 != requestHeader.getQueueOffset()) { + response.setCode(MQResponseCode.PULL_OFFSET_MOVED_VALUE); + + log.info( + "the broker store no queue data, fix the request offset {} to {}, Topic: {} QueueId: {} Consumer Group: {}",// + requestHeader.getQueueOffset(), // + getMessageResult.getNextBeginOffset(), // + requestHeader.getTopic(),// + requestHeader.getQueueId(),// + requestHeader.getConsumerGroup()// + ); + } + else { + response.setCode(MQResponseCode.PULL_NOT_FOUND_VALUE); + } break; case NO_MATCHED_MESSAGE: response.setCode(MQResponseCode.PULL_RETRY_IMMEDIATELY_VALUE); @@ -178,8 +319,8 @@ private RemotingCommand processRequest(final Channel channel, RemotingCommand re case OFFSET_TOO_SMALL: response.setCode(MQResponseCode.PULL_OFFSET_MOVED_VALUE); log.info("the request offset: " + requestHeader.getQueueOffset() - + " too small, broker min offset: " + getMessageResult.getMinOffset() + ", consumer: " - + channel.remoteAddress()); + + " too small, broker min offset: " + getMessageResult.getMinOffset() + + ", consumer: " + channel.remoteAddress()); break; default: assert false; @@ -190,14 +331,15 @@ private RemotingCommand processRequest(final Channel channel, RemotingCommand re case ResponseCode.SUCCESS_VALUE: try { FileRegion fileRegion = - new ManyMessageTransfer(response.encodeHeader(getMessageResult.getBufferTotalSize()), - getMessageResult); - channel.sendFile(fileRegion).addListener(new ChannelFutureListener() { + new ManyMessageTransfer(response.encodeHeader(getMessageResult + .getBufferTotalSize()), getMessageResult); + channel.writeAndFlush(fileRegion).addListener(new ChannelFutureListener() { @Override public void operationComplete(ChannelFuture future) throws Exception { getMessageResult.release(); if (!future.isSuccess()) { - log.error("transfer many message by pagecache failed, " + channel.remoteAddress(), + log.error( + "transfer many message by pagecache failed, " + channel.remoteAddress(), future.cause()); } } @@ -211,18 +353,18 @@ public void operationComplete(ChannelFuture future) throws Exception { response = null; break; case MQResponseCode.PULL_NOT_FOUND_VALUE: - // ѯ + // 长轮询 if (brokerAllowSuspend && hasSuspendFlag) { PullRequest pullRequest = new PullRequest(request, channel, suspendTimeoutMillisLong, this.brokerController .getMessageStore().now(), requestHeader.getQueueOffset()); - this.brokerController.getPullRequestHoldService().suspendPullRequest(requestHeader.getTopic(), - requestHeader.getQueueId(), pullRequest); + this.brokerController.getPullRequestHoldService().suspendPullRequest( + requestHeader.getTopic(), requestHeader.getQueueId(), pullRequest); response = null; break; } - // ConsumerӦ + // 向Consumer返回应答 case MQResponseCode.PULL_RETRY_IMMEDIATELY_VALUE: case MQResponseCode.PULL_OFFSET_MOVED_VALUE: break; @@ -235,12 +377,14 @@ public void operationComplete(ChannelFuture future) throws Exception { response.setRemark("store getMessage return null"); } - // 洢Consumerѽ - if (brokerAllowSuspend) { // ˵״εãڳѯ֪ͨ - if (hasCommitOffsetFlag) { - this.brokerController.getConsumerOffsetManager().commitOffset(requestHeader.getConsumerGroup(), - requestHeader.getTopic(), requestHeader.getQueueId(), requestHeader.getCommitOffset()); - } + // 存储Consumer消费进度 + boolean storeOffsetEnable = brokerAllowSuspend; // 说明是首次调用,相对于长轮询通知 + storeOffsetEnable = storeOffsetEnable && hasCommitOffsetFlag; // 说明Consumer设置了标志位 + storeOffsetEnable = storeOffsetEnable // 只有Master支持存储offset + && this.brokerController.getMessageStoreConfig().getBrokerRole() != BrokerRole.SLAVE; + if (storeOffsetEnable) { + this.brokerController.getConsumerOffsetManager().commitOffset(requestHeader.getConsumerGroup(), + requestHeader.getTopic(), requestHeader.getQueueId(), requestHeader.getCommitOffset()); } return response; diff --git a/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/processor/QueryMessageProcessor.java b/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/processor/QueryMessageProcessor.java index 82e64d89..a7b10ebe 100644 --- a/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/processor/QueryMessageProcessor.java +++ b/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/processor/QueryMessageProcessor.java @@ -1,5 +1,17 @@ /** - * $Id: QueryMessageProcessor.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.broker.processor; @@ -14,9 +26,7 @@ import com.alibaba.rocketmq.broker.BrokerController; import com.alibaba.rocketmq.broker.pagecache.OneMessageTransfer; import com.alibaba.rocketmq.broker.pagecache.QueryMessageTransfer; -import com.alibaba.rocketmq.common.MessageExt; -import com.alibaba.rocketmq.common.MessageDecoder; -import com.alibaba.rocketmq.common.MixAll; +import com.alibaba.rocketmq.common.constant.LoggerName; import com.alibaba.rocketmq.common.protocol.MQProtos.MQRequestCode; import com.alibaba.rocketmq.common.protocol.MQProtos.MQResponseCode; import com.alibaba.rocketmq.common.protocol.header.QueryMessageRequestHeader; @@ -31,11 +41,13 @@ /** - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * 查询消息请求处理 * + * @author shijia.wxr + * @since 2013-7-26 */ public class QueryMessageProcessor implements NettyRequestProcessor { - private static final Logger log = LoggerFactory.getLogger(MixAll.BrokerLoggerName); + private static final Logger log = LoggerFactory.getLogger(LoggerName.BrokerLoggerName); private final BrokerController brokerController; @@ -64,12 +76,25 @@ public RemotingCommand processRequest(ChannelHandlerContext ctx, RemotingCommand public RemotingCommand queryMessage(ChannelHandlerContext ctx, RemotingCommand request) throws RemotingCommandException { - final RemotingCommand response = RemotingCommand.createResponseCommand(QueryMessageResponseHeader.class); - final QueryMessageResponseHeader responseHeader = (QueryMessageResponseHeader) response.getCustomHeader(); + final RemotingCommand response = + RemotingCommand.createResponseCommand(QueryMessageResponseHeader.class); + final QueryMessageResponseHeader responseHeader = + (QueryMessageResponseHeader) response.getCustomHeader(); final QueryMessageRequestHeader requestHeader = - (QueryMessageRequestHeader) request.decodeCommandCustomHeader(QueryMessageRequestHeader.class); + (QueryMessageRequestHeader) request + .decodeCommandCustomHeader(QueryMessageRequestHeader.class); + + // 校验查询时间范围 + long maxTimeSpan = + this.brokerController.getBrokerConfig().getQueryMessageMaxTimeSpan() * 60 * 60 * 1000; + long diff = requestHeader.getEndTimestamp() - requestHeader.getBeginTimestamp(); + if (diff > maxTimeSpan) { + response.setCode(ResponseCode.SYSTEM_ERROR_VALUE); + response.setRemark("the time range is too long, broker limits " + maxTimeSpan + "h"); + return response; + } - // ʹsendfileԱҪ + // 由于使用sendfile,所以必须要设置 response.setOpaque(request.getOpaque()); final QueryMessageResult queryMessageResult = @@ -81,16 +106,16 @@ public RemotingCommand queryMessage(ChannelHandlerContext ctx, RemotingCommand r responseHeader.setIndexLastUpdatePhyoffset(queryMessageResult.getIndexLastUpdatePhyoffset()); responseHeader.setIndexLastUpdateTimestamp(queryMessageResult.getIndexLastUpdateTimestamp()); - // ˵ҵϢ + // 说明找到消息 if (queryMessageResult.getBufferTotalSize() > 0) { response.setCode(ResponseCode.SUCCESS_VALUE); response.setRemark(null); try { FileRegion fileRegion = - new QueryMessageTransfer(response.encodeHeader(queryMessageResult.getBufferTotalSize()), - queryMessageResult); - ctx.channel().sendFile(fileRegion).addListener(new ChannelFutureListener() { + new QueryMessageTransfer(response.encodeHeader(queryMessageResult + .getBufferTotalSize()), queryMessageResult); + ctx.channel().writeAndFlush(fileRegion).addListener(new ChannelFutureListener() { @Override public void operationComplete(ChannelFuture future) throws Exception { queryMessageResult.release(); @@ -120,44 +145,35 @@ public RemotingCommand viewMessageById(ChannelHandlerContext ctx, RemotingComman final ViewMessageRequestHeader requestHeader = (ViewMessageRequestHeader) request.decodeCommandCustomHeader(ViewMessageRequestHeader.class); - // ʹsendfileԱҪ + // 由于使用sendfile,所以必须要设置 response.setOpaque(request.getOpaque()); final SelectMapedBufferResult selectMapedBufferResult = this.brokerController.getMessageStore().selectOneMessageByOffset(requestHeader.getOffset()); if (selectMapedBufferResult != null) { - // УMessageϷ - MessageExt msgExt = MessageDecoder.decode(selectMapedBufferResult.getByteBuffer(), true); - if (null == msgExt) { - response.setCode(ResponseCode.SYSTEM_ERROR_VALUE); - response.setRemark("The offset: " + requestHeader.getOffset() + " not match any message."); - } - // Messageͻ - else { - response.setCode(ResponseCode.SUCCESS_VALUE); - response.setRemark(null); - - try { - FileRegion fileRegion = - new OneMessageTransfer(response.encodeHeader(selectMapedBufferResult.getSize()), - selectMapedBufferResult); - ctx.channel().sendFile(fileRegion).addListener(new ChannelFutureListener() { - @Override - public void operationComplete(ChannelFuture future) throws Exception { - selectMapedBufferResult.release(); - if (!future.isSuccess()) { - log.error("transfer one message by pagecache failed, ", future.cause()); - } + response.setCode(ResponseCode.SUCCESS_VALUE); + response.setRemark(null); + + try { + FileRegion fileRegion = + new OneMessageTransfer(response.encodeHeader(selectMapedBufferResult.getSize()), + selectMapedBufferResult); + ctx.channel().writeAndFlush(fileRegion).addListener(new ChannelFutureListener() { + @Override + public void operationComplete(ChannelFuture future) throws Exception { + selectMapedBufferResult.release(); + if (!future.isSuccess()) { + log.error("transfer one message by pagecache failed, ", future.cause()); } - }); - } - catch (Throwable e) { - log.error("", e); - selectMapedBufferResult.release(); - } - - return null; + } + }); } + catch (Throwable e) { + log.error("", e); + selectMapedBufferResult.release(); + } + + return null; } else { response.setCode(ResponseCode.SYSTEM_ERROR_VALUE); diff --git a/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/processor/SendMessageProcessor.java b/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/processor/SendMessageProcessor.java index d50e4347..f9b75a5b 100644 --- a/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/processor/SendMessageProcessor.java +++ b/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/processor/SendMessageProcessor.java @@ -1,5 +1,17 @@ /** - * $Id: SendMessageProcessor.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.broker.processor; @@ -15,14 +27,26 @@ import org.slf4j.LoggerFactory; import com.alibaba.rocketmq.broker.BrokerController; -import com.alibaba.rocketmq.common.MessageDecoder; +import com.alibaba.rocketmq.broker.digestlog.SendbackmsgLiveMoniter; +import com.alibaba.rocketmq.broker.digestlog.SendmsgLiveMoniter; import com.alibaba.rocketmq.common.MixAll; import com.alibaba.rocketmq.common.TopicConfig; import com.alibaba.rocketmq.common.TopicFilterType; +import com.alibaba.rocketmq.common.UtilAll; +import com.alibaba.rocketmq.common.constant.LoggerName; +import com.alibaba.rocketmq.common.constant.PermName; +import com.alibaba.rocketmq.common.help.FAQUrl; +import com.alibaba.rocketmq.common.message.MessageConst; +import com.alibaba.rocketmq.common.message.MessageDecoder; +import com.alibaba.rocketmq.common.message.MessageExt; +import com.alibaba.rocketmq.common.protocol.MQProtos.MQRequestCode; import com.alibaba.rocketmq.common.protocol.MQProtos.MQResponseCode; +import com.alibaba.rocketmq.common.protocol.header.ConsumerSendMsgBackRequestHeader; import com.alibaba.rocketmq.common.protocol.header.SendMessageRequestHeader; import com.alibaba.rocketmq.common.protocol.header.SendMessageResponseHeader; +import com.alibaba.rocketmq.common.subscription.SubscriptionGroupConfig; import com.alibaba.rocketmq.common.sysflag.MessageSysFlag; +import com.alibaba.rocketmq.remoting.common.RemotingHelper; import com.alibaba.rocketmq.remoting.exception.RemotingCommandException; import com.alibaba.rocketmq.remoting.netty.NettyRequestProcessor; import com.alibaba.rocketmq.remoting.protocol.RemotingCommand; @@ -32,14 +56,15 @@ /** - * ͻ˷Ϣ - * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * 处理客户端发送消息的请求 * + * @author shijia.wxr + * @since 2013-7-26 */ public class SendMessageProcessor implements NettyRequestProcessor { - private static final Logger log = LoggerFactory.getLogger(MixAll.BrokerLoggerName); + private static final Logger log = LoggerFactory.getLogger(LoggerName.BrokerLoggerName); + private final static int DLQ_NUMS_PER_GROUP = 1; private final BrokerController brokerController; private final Random random = new Random(System.currentTimeMillis()); private final SocketAddress storeHost; @@ -54,22 +79,186 @@ public SendMessageProcessor(final BrokerController brokerController) { @Override - public RemotingCommand processRequest(final ChannelHandlerContext ctx, final RemotingCommand request) + public RemotingCommand processRequest(ChannelHandlerContext ctx, RemotingCommand request) + throws RemotingCommandException { + MQRequestCode code = MQRequestCode.valueOf(request.getCode()); + switch (code) { + case SEND_MESSAGE: + return this.sendMessage(ctx, request); + case CONSUMER_SEND_MSG_BACK: + return this.consumerSendMsgBack(ctx, request); + default: + break; + } + return null; + } + + + private RemotingCommand consumerSendMsgBack(final ChannelHandlerContext ctx, final RemotingCommand request) + throws RemotingCommandException { + final RemotingCommand response = RemotingCommand.createResponseCommand(null); + final ConsumerSendMsgBackRequestHeader requestHeader = + (ConsumerSendMsgBackRequestHeader) request + .decodeCommandCustomHeader(ConsumerSendMsgBackRequestHeader.class); + + // 确保订阅组存在 + SubscriptionGroupConfig subscriptionGroupConfig = + this.brokerController.getSubscriptionGroupManager().findSubscriptionGroupConfig( + requestHeader.getGroup()); + if (null == subscriptionGroupConfig) { + response.setCode(MQResponseCode.SUBSCRIPTION_GROUP_NOT_EXIST_VALUE); + response.setRemark("subscription group not exist, " + requestHeader.getGroup() + " " + + FAQUrl.suggestTodo(FAQUrl.SUBSCRIPTION_GROUP_NOT_EXIST)); + return response; + } + + // 如果重试队列数目为0,则直接丢弃消息 + if (subscriptionGroupConfig.getRetryQueueNums() <= 0) { + response.setCode(ResponseCode.SUCCESS_VALUE); + response.setRemark(null); + return response; + } + + String newTopic = MixAll.getRetryTopic(requestHeader.getGroup()); + int queueIdInt = + Math.abs(this.random.nextInt() % 99999999) % subscriptionGroupConfig.getRetryQueueNums(); + + // 检查topic是否存在 + TopicConfig topicConfig = + this.brokerController.getTopicConfigManager().createTopicInSendMessageBackMethod(// + newTopic,// + subscriptionGroupConfig.getRetryQueueNums(), // + PermName.PERM_WRITE | PermName.PERM_READ); + if (null == topicConfig) { + response.setCode(ResponseCode.SYSTEM_ERROR_VALUE); + response.setRemark("topic[" + newTopic + "] not exist"); + return response; + } + + // 检查topic权限 + if (!PermName.isWriteable(topicConfig.getPerm())) { + response.setCode(MQResponseCode.NO_PERMISSION_VALUE); + response.setRemark("the topic[" + newTopic + "] sending message is forbidden"); + return response; + } + + // 查询消息,这里如果堆积消息过多,会访问磁盘 + // 另外如果频繁调用,是否会引起gc问题,需要关注 TODO + MessageExt msgExt = + this.brokerController.getMessageStore().lookMessageByOffset(requestHeader.getOffset()); + if (null == msgExt) { + response.setCode(ResponseCode.SYSTEM_ERROR_VALUE); + response.setRemark("look message by offset failed, " + requestHeader.getOffset()); + return response; + } + + // 构造消息 + final String retryTopic = msgExt.getProperty(MessageConst.PROPERTY_RETRY_TOPIC); + if (null == retryTopic) { + msgExt.putProperty(MessageConst.PROPERTY_RETRY_TOPIC, msgExt.getTopic()); + } + msgExt.setWaitStoreMsgOK(false); + + // 客户端自动决定定时级别 + int delayLevel = requestHeader.getDelayLevel(); + + // 死信消息处理 + if (msgExt.getReconsumeTimes() >= subscriptionGroupConfig.getRetryMaxTimes()// + || delayLevel < 0) { + newTopic = MixAll.getDLQTopic(requestHeader.getGroup()); + queueIdInt = Math.abs(this.random.nextInt() % 99999999) % DLQ_NUMS_PER_GROUP; + + topicConfig = + this.brokerController.getTopicConfigManager().createTopicInSendMessageBackMethod( + newTopic, // + DLQ_NUMS_PER_GROUP,// + PermName.PERM_WRITE); + if (null == topicConfig) { + response.setCode(ResponseCode.SYSTEM_ERROR_VALUE); + response.setRemark("topic[" + newTopic + "] not exist"); + return response; + } + } + // 继续重试 + else { + if (0 == delayLevel) { + delayLevel = 3 + msgExt.getReconsumeTimes(); + } + + msgExt.setDelayTimeLevel(delayLevel); + } + + MessageExtBrokerInner msgInner = new MessageExtBrokerInner(); + msgInner.setTopic(newTopic); + msgInner.setBody(msgExt.getBody()); + msgInner.setFlag(msgExt.getFlag()); + msgInner.setProperties(msgExt.getProperties()); + msgInner.setPropertiesString(MessageDecoder.messageProperties2String(msgExt.getProperties())); + msgInner.setTagsCode(MessageExtBrokerInner.tagsString2tagsCode(null, msgExt.getTags())); + + msgInner.setQueueId(queueIdInt); + msgInner.setSysFlag(msgExt.getSysFlag()); + msgInner.setBornTimestamp(msgExt.getBornTimestamp()); + msgInner.setBornHost(msgExt.getBornHost()); + msgInner.setStoreHost(this.getStoreHost()); + msgInner.setReconsumeTimes(msgExt.getReconsumeTimes() + 1); + + PutMessageResult putMessageResult = this.brokerController.getMessageStore().putMessage(msgInner); + SendbackmsgLiveMoniter.printProcessSendmsgRequestLive(ctx.channel(), request, putMessageResult, + delayLevel, msgExt.getReconsumeTimes()); + if (putMessageResult != null) { + switch (putMessageResult.getPutMessageStatus()) { + case PUT_OK: + response.setCode(ResponseCode.SUCCESS_VALUE); + response.setRemark(null); + return response; + default: + break; + } + + response.setCode(ResponseCode.SYSTEM_ERROR_VALUE); + response.setRemark(putMessageResult.getPutMessageStatus().name()); + return response; + } + + response.setCode(ResponseCode.SYSTEM_ERROR_VALUE); + response.setRemark("putMessageResult is null"); + return response; + } + + + private String diskUtil() { + String storePathPhysic = this.brokerController.getMessageStoreConfig().getStorePathCommitLog(); + double physicRatio = UtilAll.getDiskPartitionSpaceUsedPercent(storePathPhysic); + + String storePathLogis = this.brokerController.getMessageStoreConfig().getStorePathConsumeQueue(); + double logisRatio = UtilAll.getDiskPartitionSpaceUsedPercent(storePathLogis); + + String storePathIndex = this.brokerController.getMessageStoreConfig().getStorePathIndex(); + double indexRatio = UtilAll.getDiskPartitionSpaceUsedPercent(storePathIndex); + + return String.format("CL: %5.2f CQ: %5.2f INDEX: %5.2f", physicRatio, logisRatio, indexRatio); + } + + + private RemotingCommand sendMessage(final ChannelHandlerContext ctx, final RemotingCommand request) throws RemotingCommandException { - final RemotingCommand response = RemotingCommand.createResponseCommand(SendMessageResponseHeader.class); - final SendMessageResponseHeader responseHeader = (SendMessageResponseHeader) response.getCustomHeader(); + final RemotingCommand response = + RemotingCommand.createResponseCommand(SendMessageResponseHeader.class); + final SendMessageResponseHeader responseHeader = + (SendMessageResponseHeader) response.getCustomHeader(); final SendMessageRequestHeader requestHeader = (SendMessageRequestHeader) request.decodeCommandCustomHeader(SendMessageRequestHeader.class); - // ֱӷص߼ԱҪ + // 由于有直接返回的逻辑,所以必须要设置 response.setOpaque(request.getOpaque()); if (log.isDebugEnabled()) { log.debug("receive SendMessage request command, " + request); } - // BrokerȨ - if (!MixAll.isWriteable(this.brokerController.getBrokerConfig().getBrokerPermission())) { + // 检查Broker权限 + if (!PermName.isWriteable(this.brokerController.getBrokerConfig().getBrokerPermission())) { response.setCode(MQResponseCode.NO_PERMISSION_VALUE); response.setRemark("the broker[" + this.brokerController.getBrokerConfig().getBrokerIP1() + "] sending message is forbidden"); @@ -78,7 +267,7 @@ public RemotingCommand processRequest(final ChannelHandlerContext ctx, final Rem final byte[] body = request.getBody(); - // TopicǷ뱣ֶγͻ + // Topic名字是否与保留字段冲突 if (!this.brokerController.getTopicConfigManager().isTopicCanSendMessage(requestHeader.getTopic())) { String errorMsg = "the topic[" + requestHeader.getTopic() + "] is conflict with system reserved words."; @@ -88,31 +277,43 @@ public RemotingCommand processRequest(final ChannelHandlerContext ctx, final Rem return response; } - // topicǷ + // 检查topic是否存在 TopicConfig topicConfig = this.brokerController.getTopicConfigManager().selectTopicConfig(requestHeader.getTopic()); if (null == topicConfig) { - log.error("the topic " + requestHeader.getTopic() + " not exist, producer: " + log.warn("the topic " + requestHeader.getTopic() + " not exist, producer: " + ctx.channel().remoteAddress()); - topicConfig = - this.brokerController.getTopicConfigManager().createTopicInSendMessageMethod( - requestHeader.getTopic(), requestHeader.getDefaultTopic(), ctx, - requestHeader.getDefaultTopicQueueNums()); + topicConfig = this.brokerController.getTopicConfigManager().createTopicInSendMessageMethod(// + requestHeader.getTopic(), // + requestHeader.getDefaultTopic(), // + RemotingHelper.parseChannelRemoteAddr(ctx.channel()), // + requestHeader.getDefaultTopicQueueNums()); + + // 尝试看下是否是失败消息发回 + if (null == topicConfig) { + if (requestHeader.getTopic().startsWith(MixAll.RETRY_GROUP_TOPIC_PREFIX)) { + topicConfig = + this.brokerController.getTopicConfigManager().createTopicInSendMessageBackMethod( + requestHeader.getTopic(), 1, PermName.PERM_WRITE | PermName.PERM_READ); + } + } + if (null == topicConfig) { response.setCode(MQResponseCode.TOPIC_NOT_EXIST_VALUE); - response.setRemark("topic not exist, apply first please!"); + response.setRemark("topic[" + requestHeader.getTopic() + "] not exist, apply first please!" + + FAQUrl.suggestTodo(FAQUrl.APPLY_TOPIC_URL)); return response; } } - // topicȨ - if (!MixAll.isWriteable(topicConfig.getPerm())) { + // 检查topic权限 + if (!PermName.isWriteable(topicConfig.getPerm())) { response.setCode(MQResponseCode.NO_PERMISSION_VALUE); response.setRemark("the topic[" + requestHeader.getTopic() + "] sending message is forbidden"); return response; } - // Ч + // 检查队列有效性 int queueIdInt = requestHeader.getQueueId(); if (queueIdInt >= topicConfig.getWriteQueueNums()) { String errorInfo = @@ -124,13 +325,13 @@ public RemotingCommand processRequest(final ChannelHandlerContext ctx, final Rem return response; } - // ָһ + // 随机指定一个队列 if (queueIdInt < 0) { - queueIdInt = Math.abs(this.random.nextInt()) % topicConfig.getWriteQueueNums(); + queueIdInt = Math.abs(this.random.nextInt() % 99999999) % topicConfig.getWriteQueueNums(); } int sysFlag = requestHeader.getSysFlag(); - // ǩҪλ + // 多标签过滤需要置位 if (TopicFilterType.MULTI_TAG == topicConfig.getTopicFilterType()) { sysFlag |= MessageSysFlag.MultiTagsFlag; } @@ -152,7 +353,19 @@ public RemotingCommand processRequest(final ChannelHandlerContext ctx, final Rem msgInner.setReconsumeTimes(0); + // 检查事务消息 + if (this.brokerController.getBrokerConfig().isRejectTransactionMessage()) { + String traFlag = msgInner.getProperty(MessageConst.PROPERTY_TRANSACTION_PREPARED); + if (traFlag != null) { + response.setCode(MQResponseCode.NO_PERMISSION_VALUE); + response.setRemark("the broker[" + this.brokerController.getBrokerConfig().getBrokerIP1() + + "] sending transaction message is forbidden"); + return response; + } + } + PutMessageResult putMessageResult = this.brokerController.getMessageStore().putMessage(msgInner); + SendmsgLiveMoniter.printProcessSendmsgRequestLive(ctx.channel(), request, putMessageResult); if (putMessageResult != null) { boolean sendOK = false; @@ -186,7 +399,7 @@ public RemotingCommand processRequest(final ChannelHandlerContext ctx, final Rem break; case SERVICE_NOT_AVAILABLE: response.setCode(MQResponseCode.SERVICE_NOT_AVAILABLE_VALUE); - response.setRemark("service not available now."); + response.setRemark("service not available now, maybe disk full, " + diskUtil()); break; case UNKNOWN_ERROR: response.setCode(ResponseCode.SYSTEM_ERROR_VALUE); @@ -205,29 +418,31 @@ public RemotingCommand processRequest(final ChannelHandlerContext ctx, final Rem responseHeader.setQueueId(queueIdInt); responseHeader.setQueueOffset(putMessageResult.getAppendMessageResult().getLogicsOffset()); - // ֱӷ - try { - ctx.write(response).addListener(new ChannelFutureListener() { - @Override - public void operationComplete(ChannelFuture future) throws Exception { - if (!future.isSuccess()) { - log.error("SendMessageProcessor response to " + future.channel().remoteAddress() - + " failed", future.cause()); - log.error(request.toString()); - log.error(response.toString()); + // 直接返回 + if (!request.isOnewayRPC()) { + try { + ctx.writeAndFlush(response).addListener(new ChannelFutureListener() { + @Override + public void operationComplete(ChannelFuture future) throws Exception { + if (!future.isSuccess()) { + log.error("SendMessageProcessor response to " + + future.channel().remoteAddress() + " failed", future.cause()); + log.error(request.toString()); + log.error(response.toString()); + } } - } - }); - } - catch (Throwable e) { - log.error("SendMessageProcessor process request over, but response failed", e); - log.error(request.toString()); - log.error(response.toString()); + }); + } + catch (Throwable e) { + log.error("SendMessageProcessor process request over, but response failed", e); + log.error(request.toString()); + log.error(response.toString()); + } } - this.brokerController.getPullRequestHoldService().notifyMessageArriving(requestHeader.getTopic(), - queueIdInt, putMessageResult.getAppendMessageResult().getLogicsOffset()); - + this.brokerController.getPullRequestHoldService().notifyMessageArriving( + requestHeader.getTopic(), queueIdInt, + putMessageResult.getAppendMessageResult().getLogicsOffset()); return null; } } @@ -243,5 +458,4 @@ public void operationComplete(ChannelFuture future) throws Exception { public SocketAddress getStoreHost() { return storeHost; } - } diff --git a/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/slave/SlaveSynchronize.java b/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/slave/SlaveSynchronize.java new file mode 100644 index 00000000..4e1db95b --- /dev/null +++ b/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/slave/SlaveSynchronize.java @@ -0,0 +1,162 @@ +/** + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.rocketmq.broker.slave; + +import java.io.IOException; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.alibaba.rocketmq.broker.BrokerController; +import com.alibaba.rocketmq.broker.subscription.SubscriptionGroupManager; +import com.alibaba.rocketmq.common.MixAll; +import com.alibaba.rocketmq.common.constant.LoggerName; +import com.alibaba.rocketmq.common.protocol.body.ConsumerOffsetSerializeWrapper; +import com.alibaba.rocketmq.common.protocol.body.SubscriptionGroupWrapper; +import com.alibaba.rocketmq.common.protocol.body.TopicConfigSerializeWrapper; + + +/** + * Slave从Master同步信息(非消息) + * + * @author shijia.wxr + * @author manhong.yqd + * @since 2013-7-8 + */ +public class SlaveSynchronize { + private static final Logger log = LoggerFactory.getLogger(LoggerName.BrokerLoggerName); + private final BrokerController brokerController; + private volatile String masterAddr = null; + + + public SlaveSynchronize(BrokerController brokerController) { + this.brokerController = brokerController; + } + + + public String getMasterAddr() { + return masterAddr; + } + + + public void setMasterAddr(String masterAddr) { + this.masterAddr = masterAddr; + } + + + public void syncAll() { + this.syncTopicConfig(); + this.syncConsumerOffset(); + this.syncDelayOffset(); + this.syncSubscriptionGroupConfig(); + } + + + private void syncTopicConfig() { + String masterAddrBak = this.masterAddr; + if (masterAddrBak != null) { + try { + TopicConfigSerializeWrapper topicWrapper = + this.brokerController.getBrokerOuterAPI().getAllTopicConfig(masterAddrBak); + if (!this.brokerController.getTopicConfigManager().getDataVersion() + .equals(topicWrapper.getDataVersion())) { + + this.brokerController.getTopicConfigManager().getDataVersion() + .assignNewOne(topicWrapper.getDataVersion()); + this.brokerController.getTopicConfigManager().getTopicConfigTable().clear(); + this.brokerController.getTopicConfigManager().getTopicConfigTable() + .putAll(topicWrapper.getTopicConfigTable()); + this.brokerController.getTopicConfigManager().persist(); + + log.info("update slave topic config from master, {}", masterAddrBak); + } + } + catch (Exception e) { + log.error("syncTopicConfig Exception, " + masterAddrBak, e); + } + } + } + + + private void syncConsumerOffset() { + String masterAddrBak = this.masterAddr; + if (masterAddrBak != null) { + try { + ConsumerOffsetSerializeWrapper offsetWrapper = + this.brokerController.getBrokerOuterAPI().getAllConsumerOffset(masterAddrBak); + this.brokerController.getConsumerOffsetManager().getOffsetTable() + .putAll(offsetWrapper.getOffsetTable()); + this.brokerController.getConsumerOffsetManager().persist(); + log.info("update slave consumer offset from master, {}", masterAddrBak); + } + catch (Exception e) { + log.error("syncConsumerOffset Exception, " + masterAddrBak, e); + } + } + } + + + private void syncDelayOffset() { + String masterAddrBak = this.masterAddr; + if (masterAddrBak != null) { + try { + String delayOffset = + this.brokerController.getBrokerOuterAPI().getAllDelayOffset(masterAddrBak); + if (delayOffset != null) { + String fileName = this.brokerController.getMessageStoreConfig().getDelayOffsetStorePath(); + try { + MixAll.string2File(delayOffset, fileName); + } + catch (IOException e) { + log.error("persist file Exception, " + fileName, e); + } + } + log.info("update slave delay offset from master, {}", masterAddrBak); + } + catch (Exception e) { + log.error("syncDelayOffset Exception, " + masterAddrBak, e); + } + } + } + + + private void syncSubscriptionGroupConfig() { + String masterAddrBak = this.masterAddr; + if (masterAddrBak != null) { + try { + SubscriptionGroupWrapper subscriptionWrapper = + this.brokerController.getBrokerOuterAPI() + .getAllSubscriptionGroupConfig(masterAddrBak); + + if (!this.brokerController.getSubscriptionGroupManager().getDataVersion() + .equals(subscriptionWrapper.getDataVersion())) { + SubscriptionGroupManager subscriptionGroupManager = + this.brokerController.getSubscriptionGroupManager(); + subscriptionGroupManager.getDataVersion().assignNewOne( + subscriptionWrapper.getDataVersion()); + subscriptionGroupManager.getSubscriptionGroupTable().clear(); + subscriptionGroupManager.getSubscriptionGroupTable().putAll( + subscriptionWrapper.getSubscriptionGroupTable()); + subscriptionGroupManager.persist(); + log.info("update slave Subscription Group from master, {}", masterAddrBak); + } + } + catch (Exception e) { + log.error("syncSubscriptionGroup Exception, " + masterAddrBak, e); + } + } + } +} diff --git a/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/stats/BrokerStats.java b/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/stats/BrokerStats.java new file mode 100644 index 00000000..ae3ff472 --- /dev/null +++ b/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/stats/BrokerStats.java @@ -0,0 +1,117 @@ +/** + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.rocketmq.broker.stats; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.alibaba.rocketmq.common.constant.LoggerName; +import com.alibaba.rocketmq.store.DefaultMessageStore; + + +/** + * Broker上的一些统计数据 + * + * @author shijia.wxr + * @since 2013-10-23 + */ +public class BrokerStats { + private static final Logger log = LoggerFactory.getLogger(LoggerName.BrokerLoggerName); + + // 昨天凌晨00:00:00记录的put消息总数 + private volatile long msgPutTotalYesterdayMorning; + // 今天凌晨00:00:00记录的put消息总数 + private volatile long msgPutTotalTodayMorning; + + // 昨天凌晨00:00:00记录的get消息总数 + private volatile long msgGetTotalYesterdayMorning; + // 今天凌晨00:00:00记录的get消息总数 + private volatile long msgGetTotalTodayMorning; + + private final DefaultMessageStore defaultMessageStore; + + + public BrokerStats(DefaultMessageStore defaultMessageStore) { + this.defaultMessageStore = defaultMessageStore; + } + + + /** + * 每天00:00:00调用 + */ + public void record() { + this.msgPutTotalYesterdayMorning = this.msgPutTotalTodayMorning; + this.msgGetTotalYesterdayMorning = this.msgGetTotalTodayMorning; + + this.msgPutTotalTodayMorning = + this.defaultMessageStore.getStoreStatsService().getPutMessageTimesTotal(); + this.msgGetTotalTodayMorning = + this.defaultMessageStore.getStoreStatsService().getGetMessageTransferedMsgCount().get(); + + log.info("yesterday put message total: {}", msgPutTotalTodayMorning - msgPutTotalYesterdayMorning); + log.info("yesterday get message total: {}", msgGetTotalTodayMorning - msgGetTotalYesterdayMorning); + } + + + public long getMsgPutTotalYesterdayMorning() { + return msgPutTotalYesterdayMorning; + } + + + public void setMsgPutTotalYesterdayMorning(long msgPutTotalYesterdayMorning) { + this.msgPutTotalYesterdayMorning = msgPutTotalYesterdayMorning; + } + + + public long getMsgPutTotalTodayMorning() { + return msgPutTotalTodayMorning; + } + + + public void setMsgPutTotalTodayMorning(long msgPutTotalTodayMorning) { + this.msgPutTotalTodayMorning = msgPutTotalTodayMorning; + } + + + public long getMsgGetTotalYesterdayMorning() { + return msgGetTotalYesterdayMorning; + } + + + public void setMsgGetTotalYesterdayMorning(long msgGetTotalYesterdayMorning) { + this.msgGetTotalYesterdayMorning = msgGetTotalYesterdayMorning; + } + + + public long getMsgGetTotalTodayMorning() { + return msgGetTotalTodayMorning; + } + + + public void setMsgGetTotalTodayMorning(long msgGetTotalTodayMorning) { + this.msgGetTotalTodayMorning = msgGetTotalTodayMorning; + } + + + public long getMsgPutTotalTodayNow() { + return this.defaultMessageStore.getStoreStatsService().getPutMessageTimesTotal(); + } + + + public long getMsgGetTotalTodayNow() { + return this.defaultMessageStore.getStoreStatsService().getGetMessageTransferedMsgCount().get(); + } +} diff --git a/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/subscription/SubscriptionGroupManager.java b/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/subscription/SubscriptionGroupManager.java new file mode 100644 index 00000000..db9566d8 --- /dev/null +++ b/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/subscription/SubscriptionGroupManager.java @@ -0,0 +1,162 @@ +/** + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.rocketmq.broker.subscription; + +import java.util.Iterator; +import java.util.Map.Entry; +import java.util.concurrent.ConcurrentHashMap; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.alibaba.rocketmq.broker.BrokerController; +import com.alibaba.rocketmq.common.ConfigManager; +import com.alibaba.rocketmq.common.DataVersion; +import com.alibaba.rocketmq.common.MixAll; +import com.alibaba.rocketmq.common.constant.LoggerName; +import com.alibaba.rocketmq.common.subscription.SubscriptionGroupConfig; +import com.alibaba.rocketmq.remoting.protocol.RemotingSerializable; + + +/** + * 用来管理订阅组,包括订阅权限等 + * + * @author shijia.wxr + * @since 2013-7-26 + */ +public class SubscriptionGroupManager extends ConfigManager { + private static final Logger log = LoggerFactory.getLogger(LoggerName.BrokerLoggerName); + private transient BrokerController brokerController; + + // 订阅组 + private final ConcurrentHashMap subscriptionGroupTable = + new ConcurrentHashMap(1024); + private final DataVersion dataVersion = new DataVersion(); + + + private void init() { + SubscriptionGroupConfig subscriptionGroupConfig = new SubscriptionGroupConfig(); + subscriptionGroupConfig.setGroupName(MixAll.TOOLS_CONSUMER_GROUP); + this.subscriptionGroupTable.put(MixAll.TOOLS_CONSUMER_GROUP, subscriptionGroupConfig); + } + + + public SubscriptionGroupManager() { + this.init(); + } + + + public SubscriptionGroupManager(BrokerController brokerController) { + this.brokerController = brokerController; + this.init(); + } + + + public void updateSubscriptionGroupConfig(final SubscriptionGroupConfig config) { + SubscriptionGroupConfig old = this.subscriptionGroupTable.put(config.getGroupName(), config); + if (old != null) { + log.info("update subscription group config, old: " + old + " new: " + config); + } + else { + log.info("create new subscription group, " + config); + } + + this.dataVersion.nextVersion(); + + this.persist(); + } + + + public SubscriptionGroupConfig findSubscriptionGroupConfig(final String group) { + SubscriptionGroupConfig subscriptionGroupConfig = this.subscriptionGroupTable.get(group); + if (null == subscriptionGroupConfig) { + if (brokerController.getBrokerConfig().isAutoCreateSubscriptionGroup()) { + subscriptionGroupConfig = new SubscriptionGroupConfig(); + subscriptionGroupConfig.setGroupName(group); + this.subscriptionGroupTable.putIfAbsent(group, subscriptionGroupConfig); + log.info("auto create a subscription group, {}", subscriptionGroupConfig.toString()); + this.dataVersion.nextVersion(); + this.persist(); + } + } + + return subscriptionGroupConfig; + } + + + @Override + public String encode() { + return this.encode(false); + } + + + public String encode(final boolean prettyFormat) { + return RemotingSerializable.toJson(this, prettyFormat); + } + + + @Override + public void decode(String jsonString) { + if (jsonString != null) { + SubscriptionGroupManager obj = + RemotingSerializable.fromJson(jsonString, SubscriptionGroupManager.class); + if (obj != null) { + this.subscriptionGroupTable.putAll(obj.subscriptionGroupTable); + this.dataVersion.assignNewOne(obj.dataVersion); + this.printLoadDataWhenFirstBoot(obj); + } + } + } + + + private void printLoadDataWhenFirstBoot(final SubscriptionGroupManager sgm) { + Iterator> it = + sgm.getSubscriptionGroupTable().entrySet().iterator(); + while (it.hasNext()) { + Entry next = it.next(); + log.info("load exist subscription group, {}", next.getValue().toString()); + } + } + + + @Override + public String configFilePath() { + return this.brokerController.getBrokerConfig().getSubscriptionGroupPath(); + } + + + public ConcurrentHashMap getSubscriptionGroupTable() { + return subscriptionGroupTable; + } + + + public DataVersion getDataVersion() { + return dataVersion; + } + + + public void deleteSubscriptionGroupConfig(final String groupName) { + SubscriptionGroupConfig old = this.subscriptionGroupTable.remove(groupName); + if (old != null) { + log.info("delete subscription group OK, subscription group: " + old); + this.dataVersion.nextVersion(); + this.persist(); + } + else { + log.warn("delete subscription group failed, subscription group: " + old + " not exist"); + } + } +} diff --git a/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/topic/TopicConfigManager.java b/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/topic/TopicConfigManager.java index cba3b420..8d30e411 100644 --- a/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/topic/TopicConfigManager.java +++ b/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/topic/TopicConfigManager.java @@ -1,135 +1,108 @@ /** - * $Id: TopicConfigManager.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.broker.topic; -import static com.alibaba.rocketmq.common.protocol.route.ObjectConverter.props2TopicConfigTable; -import io.netty.channel.ChannelHandlerContext; - -import java.util.Properties; +import java.util.Iterator; +import java.util.Map.Entry; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; -import org.apache.commons.io.IOUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.alibaba.rocketmq.broker.BrokerController; +import com.alibaba.rocketmq.common.ConfigManager; import com.alibaba.rocketmq.common.DataVersion; import com.alibaba.rocketmq.common.MixAll; import com.alibaba.rocketmq.common.TopicConfig; +import com.alibaba.rocketmq.common.constant.LoggerName; +import com.alibaba.rocketmq.common.constant.PermName; +import com.alibaba.rocketmq.common.protocol.body.TopicConfigSerializeWrapper; import com.alibaba.rocketmq.store.schedule.ScheduleMessageService; /** - * @author vintage.wang@gmail.com shijia.wxr@taobao.com - * @author lansheng.zj@taobao.com + * Topic配置管理 * + * @author shijia.wxr + * @author lansheng.zj@taobao.com + * @since 2013-7-26 */ -public class TopicConfigManager { - private static final Logger log = LoggerFactory.getLogger(MixAll.BrokerLoggerName); +public class TopicConfigManager extends ConfigManager { + private static final Logger log = LoggerFactory.getLogger(LoggerName.BrokerLoggerName); + private static final long LockTimeoutMillis = 3000; + private transient final Lock lockTopicConfigTable = new ReentrantLock(); + private transient BrokerController brokerController; - // Topic + // Topic配置 private final ConcurrentHashMap topicConfigTable = new ConcurrentHashMap(1024); - private final Lock lockTopicConfigTable = new ReentrantLock(); - private static final long LockTimeoutMillis = 3000; - private final DataVersion dataVersion = new DataVersion(); - private final BrokerController brokerController; + + public TopicConfigManager() { + } public TopicConfigManager(BrokerController brokerController) { this.brokerController = brokerController; - - // MixAll.DEFAULT_TOPIC - TopicConfig topicConfig = new TopicConfig(MixAll.DEFAULT_TOPIC); - topicConfig.setReadQueueNums(this.brokerController.getBrokerConfig().getDefaultTopicQueueNums()); - topicConfig.setWriteQueueNums(this.brokerController.getBrokerConfig().getDefaultTopicQueueNums()); - int perm = this.brokerController.getBrokerConfig().isAutoCreateTopic() ? MixAll.PERM_INHERIT : 0; - perm |= MixAll.PERM_READ | MixAll.PERM_WRITE; - topicConfig.setPerm(perm); - this.topicConfigTable.put(topicConfig.getTopicName(), topicConfig); - - // MixAll.SELF_TEST_TOPIC - topicConfig = new TopicConfig(MixAll.SELF_TEST_TOPIC); - topicConfig.setReadQueueNums(1); - topicConfig.setWriteQueueNums(1); - this.topicConfigTable.put(topicConfig.getTopicName(), topicConfig); - - // Ⱥ - topicConfig = new TopicConfig(this.brokerController.getBrokerConfig().getBrokerClusterName()); - perm = MixAll.PERM_INHERIT; - if (this.brokerController.getBrokerConfig().isClusterTopicEnable()) { - perm |= MixAll.PERM_READ | MixAll.PERM_WRITE; + { + // MixAll.SELF_TEST_TOPIC + TopicConfig topicConfig = new TopicConfig(MixAll.SELF_TEST_TOPIC); + topicConfig.setReadQueueNums(1); + topicConfig.setWriteQueueNums(1); + this.topicConfigTable.put(topicConfig.getTopicName(), topicConfig); } - topicConfig.setPerm(perm); - this.topicConfigTable.put(topicConfig.getTopicName(), topicConfig); - } - - - public boolean load() { - try { - String fileName = this.brokerController.getBrokerConfig().getTopicConfigPath(); - String content = MixAll.file2String(fileName); - if (content != null) { - Properties prop = MixAll.string2Properties(content); - if (prop != null) { - return this.decode(prop); - } + { + // MixAll.DEFAULT_TOPIC + if (this.brokerController.getBrokerConfig().isAutoCreateTopicEnable()) { + TopicConfig topicConfig = new TopicConfig(MixAll.DEFAULT_TOPIC); + topicConfig.setReadQueueNums(this.brokerController.getBrokerConfig() + .getDefaultTopicQueueNums()); + topicConfig.setWriteQueueNums(this.brokerController.getBrokerConfig() + .getDefaultTopicQueueNums()); + int perm = PermName.PERM_INHERIT | PermName.PERM_READ | PermName.PERM_WRITE; + topicConfig.setPerm(perm); + this.topicConfigTable.put(topicConfig.getTopicName(), topicConfig); } } - catch (Exception e) { + { + // MixAll.BENCHMARK_TOPIC + TopicConfig topicConfig = new TopicConfig(MixAll.BENCHMARK_TOPIC); + topicConfig.setReadQueueNums(1024); + topicConfig.setWriteQueueNums(1024); + this.topicConfigTable.put(topicConfig.getTopicName(), topicConfig); } - - return true; - } - - - public String getCurrentDataVersion() { - return this.dataVersion.currentVersion(); - } - - - public String encodeIncludeSysTopic() { - return this.encode(true); - } - - - public String encodeNotIncludeSysTopic() { - return this.encode(false); - } - - - private String encode(boolean includeSysTopic) { - if (!this.topicConfigTable.isEmpty()) { - StringBuilder sb = new StringBuilder(); - for (TopicConfig config : this.topicConfigTable.values()) { - if (!includeSysTopic) { - if (this.isSystemTopic(config.getTopicName())) - continue; - } - - sb.append(config.getTopicName() + "=" + config.encode() + IOUtils.LINE_SEPARATOR); + { + // 集群名字 + TopicConfig topicConfig = + new TopicConfig(this.brokerController.getBrokerConfig().getBrokerClusterName()); + int perm = PermName.PERM_INHERIT; + if (this.brokerController.getBrokerConfig().isClusterTopicEnable()) { + perm |= PermName.PERM_READ | PermName.PERM_WRITE; } - - return sb.toString(); + topicConfig.setPerm(perm); + this.topicConfigTable.put(topicConfig.getTopicName(), topicConfig); } - - return null; } - private boolean decode(final Properties prop) { - topicConfigTable.putAll(props2TopicConfigTable(prop, log)); - return true; - } - - - private boolean isSystemTopic(final String topic) { + public boolean isSystemTopic(final String topic) { boolean res = // topic.equals(MixAll.DEFAULT_TOPIC)// || topic.equals(MixAll.SELF_TEST_TOPIC)// @@ -150,83 +123,130 @@ public boolean isTopicCanSendMessage(final String topic) { } - public synchronized void flush() { - String content = this.encodeNotIncludeSysTopic(); - if (content != null) { - String fileName = this.brokerController.getBrokerConfig().getTopicConfigPath(); - boolean result = MixAll.string2File(content, fileName); - log.info("flush topic config, " + fileName + (result ? " OK" : " Failed")); - } - - this.dataVersion.nextVersion(); - } - - public TopicConfig selectTopicConfig(final String topic) { return this.topicConfigTable.get(topic); } /** - * ϢʱTopicڣԴ + * 发消息时,如果Topic不存在,尝试创建 */ public TopicConfig createTopicInSendMessageMethod(final String topic, final String defaultTopic, - final ChannelHandlerContext ctx, final int clientDefaultTopicQueueNums) { - final String remoteAddress = ctx != null ? ctx.channel().remoteAddress().toString() : "UNKNOW ADDR"; + final String remoteAddress, final int clientDefaultTopicQueueNums) { + TopicConfig topicConfig = null; + boolean createNew = false; try { if (this.lockTopicConfigTable.tryLock(LockTimeoutMillis, TimeUnit.MILLISECONDS)) { - TopicConfig topicConfig = this.topicConfigTable.get(topic); - if (topicConfig != null) - return topicConfig; - - TopicConfig defaultTopicConfig = this.topicConfigTable.get(defaultTopic); - if (defaultTopicConfig != null) { - if (MixAll.isInherited(defaultTopicConfig.getPerm())) { - topicConfig = new TopicConfig(topic); - - int queueNums = - clientDefaultTopicQueueNums > defaultTopicConfig.getWriteQueueNums() ? defaultTopicConfig - .getWriteQueueNums() : clientDefaultTopicQueueNums; - - if (queueNums < 0) { - queueNums = 0; + try { + topicConfig = this.topicConfigTable.get(topic); + if (topicConfig != null) + return topicConfig; + + TopicConfig defaultTopicConfig = this.topicConfigTable.get(defaultTopic); + if (defaultTopicConfig != null) { + if (PermName.isInherited(defaultTopicConfig.getPerm())) { + topicConfig = new TopicConfig(topic); + + int queueNums = + clientDefaultTopicQueueNums > defaultTopicConfig.getWriteQueueNums() ? defaultTopicConfig + .getWriteQueueNums() : clientDefaultTopicQueueNums; + + if (queueNums < 0) { + queueNums = 0; + } + + topicConfig.setReadQueueNums(queueNums); + topicConfig.setWriteQueueNums(queueNums); + int perm = defaultTopicConfig.getPerm(); + perm &= ~PermName.PERM_INHERIT; + topicConfig.setPerm(perm); + topicConfig.setTopicFilterType(defaultTopicConfig.getTopicFilterType()); + } + else { + log.warn("create new topic failed, because the default topic[" + defaultTopic + + "] no perm, " + defaultTopicConfig.getPerm() + " producer: " + + remoteAddress); } - - topicConfig.setReadQueueNums(queueNums); - topicConfig.setWriteQueueNums(queueNums); - int perm = defaultTopicConfig.getPerm(); - perm &= ~MixAll.PERM_INHERIT; - topicConfig.setPerm(perm); - topicConfig.setTopicFilterType(defaultTopicConfig.getTopicFilterType()); } else { log.warn("create new topic failed, because the default topic[" + defaultTopic - + "] no perm, " + defaultTopicConfig.getPerm() + " producer: " + remoteAddress); + + "] not exist." + " producer: " + remoteAddress); + } + + if (topicConfig != null) { + log.info("create new topic by default topic[" + defaultTopic + "], " + topicConfig + + " producer: " + remoteAddress); + + this.topicConfigTable.put(topic, topicConfig); + + this.dataVersion.nextVersion(); + + createNew = true; + + this.persist(); } } - else { - log.warn("create new topic failed, because the default topic[" + defaultTopic + "] not exist." - + " producer: " + remoteAddress); + finally { + this.lockTopicConfigTable.unlock(); } + } + } + catch (InterruptedException e) { + log.error("createTopicInSendMessageMethod exception", e); + } - if (topicConfig != null) { - log.info("create new topic by default topic[" + defaultTopic + "], " + topicConfig - + " producer: " + remoteAddress); + if (createNew) { + this.brokerController.registerBrokerAll(); + } - this.topicConfigTable.put(topic, topicConfig); + return topicConfig; + } - this.flush(); - } - return topicConfig; + public TopicConfig createTopicInSendMessageBackMethod(// + final String topic, // + final int clientDefaultTopicQueueNums,// + final int perm// + ) { + TopicConfig topicConfig = this.topicConfigTable.get(topic); + if (topicConfig != null) + return topicConfig; + + boolean createNew = false; + + try { + if (this.lockTopicConfigTable.tryLock(LockTimeoutMillis, TimeUnit.MILLISECONDS)) { + try { + topicConfig = this.topicConfigTable.get(topic); + if (topicConfig != null) + return topicConfig; + + topicConfig = new TopicConfig(topic); + topicConfig.setReadQueueNums(clientDefaultTopicQueueNums); + topicConfig.setWriteQueueNums(clientDefaultTopicQueueNums); + topicConfig.setPerm(perm); + + log.info("create new topic {}", topicConfig); + this.topicConfigTable.put(topic, topicConfig); + createNew = true; + this.dataVersion.nextVersion(); + this.persist(); + } + finally { + this.lockTopicConfigTable.unlock(); + } } } catch (InterruptedException e) { - log.error("createTopicInSendMessageMethod exception", e); + log.error("createTopicInSendMessageBackMethod exception", e); } - return null; + if (createNew) { + this.brokerController.registerBrokerAll(); + } + + return topicConfig; } @@ -239,7 +259,11 @@ public void updateTopicConfig(final TopicConfig topicConfig) { log.info("create new topic, " + topicConfig); } - this.flush(); + this.dataVersion.nextVersion(); + + this.brokerController.registerBrokerAll(); + + this.persist(); } @@ -247,10 +271,72 @@ public void deleteTopicConfig(final String topic) { TopicConfig old = this.topicConfigTable.remove(topic); if (old != null) { log.info("delete topic config OK, topic: " + old); - this.flush(); + this.dataVersion.nextVersion(); + this.persist(); } else { log.warn("delete topic config failed, topic: " + topic + " not exist"); } } + + + public TopicConfigSerializeWrapper buildTopicConfigSerializeWrapper() { + TopicConfigSerializeWrapper topicConfigSerializeWrapper = new TopicConfigSerializeWrapper(); + topicConfigSerializeWrapper.setTopicConfigTable(this.topicConfigTable); + topicConfigSerializeWrapper.setDataVersion(this.dataVersion); + return topicConfigSerializeWrapper; + } + + + @Override + public String encode() { + return encode(false); + } + + + public String encode(final boolean prettyFormat) { + TopicConfigSerializeWrapper topicConfigSerializeWrapper = new TopicConfigSerializeWrapper(); + topicConfigSerializeWrapper.setTopicConfigTable(this.topicConfigTable); + topicConfigSerializeWrapper.setDataVersion(this.dataVersion); + return topicConfigSerializeWrapper.toJson(prettyFormat); + } + + + @Override + public void decode(String jsonString) { + if (jsonString != null) { + TopicConfigSerializeWrapper topicConfigSerializeWrapper = + TopicConfigSerializeWrapper.fromJson(jsonString, TopicConfigSerializeWrapper.class); + if (topicConfigSerializeWrapper != null) { + this.topicConfigTable.putAll(topicConfigSerializeWrapper.getTopicConfigTable()); + this.dataVersion.assignNewOne(topicConfigSerializeWrapper.getDataVersion()); + this.printLoadDataWhenFirstBoot(topicConfigSerializeWrapper); + } + } + } + + + private void printLoadDataWhenFirstBoot(final TopicConfigSerializeWrapper tcs) { + Iterator> it = tcs.getTopicConfigTable().entrySet().iterator(); + while (it.hasNext()) { + Entry next = it.next(); + log.info("load exist local topic, {}", next.getValue().toString()); + } + } + + + @Override + public String configFilePath() { + return this.brokerController.getBrokerConfig().getTopicConfigPath(); + } + + + public DataVersion getDataVersion() { + return dataVersion; + } + + + public ConcurrentHashMap getTopicConfigTable() { + return topicConfigTable; + } } diff --git a/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/transaction/DefaultTransactionCheckExecuter.java b/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/transaction/DefaultTransactionCheckExecuter.java new file mode 100644 index 00000000..1ead28d0 --- /dev/null +++ b/rocketmq-broker/src/main/java/com/alibaba/rocketmq/broker/transaction/DefaultTransactionCheckExecuter.java @@ -0,0 +1,74 @@ +/** + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.rocketmq.broker.transaction; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.alibaba.rocketmq.broker.BrokerController; +import com.alibaba.rocketmq.broker.client.ClientChannelInfo; +import com.alibaba.rocketmq.common.constant.LoggerName; +import com.alibaba.rocketmq.common.protocol.header.CheckTransactionStateRequestHeader; +import com.alibaba.rocketmq.store.SelectMapedBufferResult; +import com.alibaba.rocketmq.store.transaction.TransactionCheckExecuter; + + +/** + * 存储层回调此接口,用来主动回查Producer的事务状态 + * + * @author shijia.wxr + * @since 2013-7-26 + */ +public class DefaultTransactionCheckExecuter implements TransactionCheckExecuter { + private static final Logger log = LoggerFactory.getLogger(LoggerName.BrokerLoggerName); + private final BrokerController brokerController; + + + public DefaultTransactionCheckExecuter(final BrokerController brokerController) { + this.brokerController = brokerController; + } + + + @Override + public void gotoCheck(int producerGroupHashCode, long tranStateTableOffset, long commitLogOffset, + int msgSize) { + // 第一步、查询Producer + final ClientChannelInfo clientChannelInfo = + this.brokerController.getProducerManager().pickProducerChannelRandomly(producerGroupHashCode); + if (null == clientChannelInfo) { + log.warn("check a producer transaction state, but not find any channel of this group[{}]", + producerGroupHashCode); + return; + } + + // 第二步、查询消息 + SelectMapedBufferResult selectMapedBufferResult = + this.brokerController.getMessageStore().selectOneMessageByOffset(commitLogOffset, msgSize); + if (null == selectMapedBufferResult) { + log.warn( + "check a producer transaction state, but not find message by commitLogOffset: {}, msgSize: ", + commitLogOffset, msgSize); + return; + } + + // 第三步、向Producer发起请求 + final CheckTransactionStateRequestHeader requestHeader = new CheckTransactionStateRequestHeader(); + requestHeader.setCommitLogOffset(commitLogOffset); + requestHeader.setTranStateTableOffset(tranStateTableOffset); + this.brokerController.getBroker2Client().checkProducerTransactionState( + clientChannelInfo.getChannel(), requestHeader, selectMapedBufferResult); + } +} diff --git a/rocketmq-broker/src/test/java/com/alibaba/rocketmq/broker/api/SendMessageTest.java b/rocketmq-broker/src/test/java/com/alibaba/rocketmq/broker/api/SendMessageTest.java index d93ea12b..d169acc0 100644 --- a/rocketmq-broker/src/test/java/com/alibaba/rocketmq/broker/api/SendMessageTest.java +++ b/rocketmq-broker/src/test/java/com/alibaba/rocketmq/broker/api/SendMessageTest.java @@ -10,9 +10,9 @@ import com.alibaba.rocketmq.client.impl.MQClientAPIImpl; import com.alibaba.rocketmq.client.producer.SendResult; import com.alibaba.rocketmq.common.BrokerConfig; -import com.alibaba.rocketmq.common.Message; -import com.alibaba.rocketmq.common.MessageDecoder; import com.alibaba.rocketmq.common.MixAll; +import com.alibaba.rocketmq.common.message.Message; +import com.alibaba.rocketmq.common.message.MessageDecoder; import com.alibaba.rocketmq.common.protocol.header.SendMessageRequestHeader; import com.alibaba.rocketmq.remoting.netty.NettyClientConfig; import com.alibaba.rocketmq.remoting.netty.NettyServerConfig; @@ -20,14 +20,16 @@ /** - * @author vintage.wang@gmail.com shijia.wxr@taobao.com - * + * @author shijia.wxr */ public class SendMessageTest { @Test public void test_sendMessage() throws Exception { - BrokerController brokerController = - new BrokerController(new BrokerConfig(), new NettyServerConfig(), new MessageStoreConfig()); + BrokerController brokerController = new BrokerController(// + new BrokerConfig(), // + new NettyServerConfig(), // + new NettyClientConfig(), // + new MessageStoreConfig()); boolean initResult = brokerController.initialize(); System.out.println("initialize " + initResult); @@ -38,7 +40,8 @@ public void test_sendMessage() throws Exception { for (int i = 0; i < 100000; i++) { String topic = "UnitTestTopic_" + i % 3; - Message msg = new Message(topic, "TAG1 TAG2", "100200300", ("Hello, Nice world\t" + i).getBytes()); + Message msg = + new Message(topic, "TAG1 TAG2", "100200300", ("Hello, Nice world\t" + i).getBytes()); msg.setDelayTimeLevel(i % 3 + 1); try { diff --git a/rocketmq-broker/src/test/java/com/alibaba/rocketmq/broker/offset/ConsumerOffsetManagerTest.java b/rocketmq-broker/src/test/java/com/alibaba/rocketmq/broker/offset/ConsumerOffsetManagerTest.java index 8b9ec2d5..bb99d644 100644 --- a/rocketmq-broker/src/test/java/com/alibaba/rocketmq/broker/offset/ConsumerOffsetManagerTest.java +++ b/rocketmq-broker/src/test/java/com/alibaba/rocketmq/broker/offset/ConsumerOffsetManagerTest.java @@ -9,19 +9,22 @@ import com.alibaba.rocketmq.broker.BrokerController; import com.alibaba.rocketmq.common.BrokerConfig; +import com.alibaba.rocketmq.remoting.netty.NettyClientConfig; import com.alibaba.rocketmq.remoting.netty.NettyServerConfig; import com.alibaba.rocketmq.store.config.MessageStoreConfig; /** - * @author vintage.wang@gmail.com shijia.wxr@taobao.com - * + * @author shijia.wxr */ public class ConsumerOffsetManagerTest { @Test public void test_flushConsumerOffset() throws Exception { - BrokerController brokerController = - new BrokerController(new BrokerConfig(), new NettyServerConfig(), new MessageStoreConfig()); + BrokerController brokerController = new BrokerController(// + new BrokerConfig(), // + new NettyServerConfig(), // + new NettyClientConfig(), // + new MessageStoreConfig()); boolean initResult = brokerController.initialize(); System.out.println("initialize " + initResult); brokerController.start(); @@ -33,44 +36,16 @@ public void test_flushConsumerOffset() throws Exception { for (int i = 0; i < 100; i++) { String group = "DIANPU_GROUP_" + i; for (int id = 0; id < 16; id++) { - consumerOffsetManager.commitOffset(group, "TOPIC_A", id, random.nextLong() % 1024 * 1024 * 1024); - consumerOffsetManager.commitOffset(group, "TOPIC_B", id, random.nextLong() % 1024 * 1024 * 1024); - consumerOffsetManager.commitOffset(group, "TOPIC_C", id, random.nextLong() % 1024 * 1024 * 1024); + consumerOffsetManager.commitOffset(group, "TOPIC_A", id, + random.nextLong() % 1024 * 1024 * 1024); + consumerOffsetManager.commitOffset(group, "TOPIC_B", id, + random.nextLong() % 1024 * 1024 * 1024); + consumerOffsetManager.commitOffset(group, "TOPIC_C", id, + random.nextLong() % 1024 * 1024 * 1024); } } - consumerOffsetManager.flush(); - - brokerController.shutdown(); - } - - - @Test - public void test_flushConsumerOffsetHistory() throws Exception { - BrokerController brokerController = - new BrokerController(new BrokerConfig(), new NettyServerConfig(), new MessageStoreConfig()); - boolean initResult = brokerController.initialize(); - System.out.println("initialize " + initResult); - brokerController.start(); - - ConsumerOffsetManager consumerOffsetManager = new ConsumerOffsetManager(brokerController); - - Random random = new Random(); - - for (int i = 0; i < 100; i++) { - String group = "DIANPU_GROUP_" + i; - for (int id = 0; id < 16; id++) { - consumerOffsetManager.commitOffset(group, "TOPIC_A", id, random.nextLong() % 1024 * 1024 * 1024); - consumerOffsetManager.commitOffset(group, "TOPIC_B", id, random.nextLong() % 1024 * 1024 * 1024); - consumerOffsetManager.commitOffset(group, "TOPIC_C", id, random.nextLong() % 1024 * 1024 * 1024); - } - } - - for (int i = 0; i < 10; i++) { - consumerOffsetManager.flushHistory(); - - Thread.sleep(1000 * 3); - } + consumerOffsetManager.persist(); brokerController.shutdown(); } diff --git a/rocketmq-broker/src/test/java/com/alibaba/rocketmq/broker/topic/TopicConfigManagerTest.java b/rocketmq-broker/src/test/java/com/alibaba/rocketmq/broker/topic/TopicConfigManagerTest.java index dcdcf63e..d9898d0a 100644 --- a/rocketmq-broker/src/test/java/com/alibaba/rocketmq/broker/topic/TopicConfigManagerTest.java +++ b/rocketmq-broker/src/test/java/com/alibaba/rocketmq/broker/topic/TopicConfigManagerTest.java @@ -11,19 +11,22 @@ import com.alibaba.rocketmq.common.BrokerConfig; import com.alibaba.rocketmq.common.MixAll; import com.alibaba.rocketmq.common.TopicConfig; +import com.alibaba.rocketmq.remoting.netty.NettyClientConfig; import com.alibaba.rocketmq.remoting.netty.NettyServerConfig; import com.alibaba.rocketmq.store.config.MessageStoreConfig; /** - * @author vintage.wang@gmail.com shijia.wxr@taobao.com - * + * @author shijia.wxr */ public class TopicConfigManagerTest { @Test public void test_flushTopicConfig() throws Exception { - BrokerController brokerController = - new BrokerController(new BrokerConfig(), new NettyServerConfig(), new MessageStoreConfig()); + BrokerController brokerController = new BrokerController(// + new BrokerConfig(), // + new NettyServerConfig(), // + new NettyClientConfig(), // + new MessageStoreConfig()); boolean initResult = brokerController.initialize(); System.out.println("initialize " + initResult); brokerController.start(); @@ -31,18 +34,20 @@ public void test_flushTopicConfig() throws Exception { TopicConfigManager topicConfigManager = new TopicConfigManager(brokerController); TopicConfig topicConfig = - topicConfigManager.createTopicInSendMessageMethod("TestTopic_SEND", MixAll.DEFAULT_TOPIC, null, 4); + topicConfigManager.createTopicInSendMessageMethod("TestTopic_SEND", MixAll.DEFAULT_TOPIC, + null, 4); assertTrue(topicConfig != null); System.out.println(topicConfig); for (int i = 0; i < 10; i++) { String topic = "UNITTEST-" + i; - topicConfig = topicConfigManager.createTopicInSendMessageMethod(topic, MixAll.DEFAULT_TOPIC, null, 4); + topicConfig = + topicConfigManager.createTopicInSendMessageMethod(topic, MixAll.DEFAULT_TOPIC, null, 4); assertTrue(topicConfig != null); } - topicConfigManager.flush(); + topicConfigManager.persist(); brokerController.shutdown(); } diff --git a/rocketmq-client/pom.xml b/rocketmq-client/pom.xml index 27f53cfc..7a236b73 100644 --- a/rocketmq-client/pom.xml +++ b/rocketmq-client/pom.xml @@ -1,14 +1,12 @@ - + com.alibaba.rocketmq rocketmq-all - 3.0.0-SNAPSHOT + 3.0.8-SNAPSHOT 4.0.0 jar - com.alibaba.rocketmq rocketmq-client rocketmq-client ${project.version} diff --git a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/ClientConfig.java b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/ClientConfig.java new file mode 100644 index 00000000..af045a2b --- /dev/null +++ b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/ClientConfig.java @@ -0,0 +1,152 @@ +/** + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.rocketmq.client; + +import com.alibaba.rocketmq.common.MixAll; +import com.alibaba.rocketmq.remoting.common.RemotingUtil; + + +/** + * Producer与Consumer的公共配置 + * + * @author shijia.wxr + * @since 2013-7-24 + */ +public class ClientConfig { + private String namesrvAddr = System.getProperty(MixAll.NAMESRV_ADDR_PROPERTY, + System.getenv(MixAll.NAMESRV_ADDR_ENV)); + private String clientIP = RemotingUtil.getLocalAddress(); + private String instanceName = System.getProperty("rocketmq.client.name", "DEFAULT"); + private int clientCallbackExecutorThreads = Runtime.getRuntime().availableProcessors(); + private int pollNameServerInteval = 1000 * 30; + private int heartbeatBrokerInterval = 1000 * 30; + private int persistConsumerOffsetInterval = 1000 * 5; + + + public String buildMQClientId() { + StringBuilder sb = new StringBuilder(); + sb.append(this.getClientIP()); + + sb.append("@"); + sb.append(this.getInstanceName()); + + return sb.toString(); + } + + + public void resetClientConfig(final ClientConfig cc) { + this.namesrvAddr = cc.namesrvAddr; + this.clientIP = cc.clientIP; + this.instanceName = cc.instanceName; + this.clientCallbackExecutorThreads = cc.clientCallbackExecutorThreads; + this.pollNameServerInteval = cc.pollNameServerInteval; + this.heartbeatBrokerInterval = cc.heartbeatBrokerInterval; + this.persistConsumerOffsetInterval = cc.persistConsumerOffsetInterval; + } + + + public ClientConfig cloneClientConfig() { + ClientConfig cc = new ClientConfig(); + cc.namesrvAddr = namesrvAddr; + cc.clientIP = clientIP; + cc.instanceName = instanceName; + cc.clientCallbackExecutorThreads = clientCallbackExecutorThreads; + cc.pollNameServerInteval = pollNameServerInteval; + cc.heartbeatBrokerInterval = heartbeatBrokerInterval; + cc.persistConsumerOffsetInterval = persistConsumerOffsetInterval; + return cc; + } + + + public String getNamesrvAddr() { + return namesrvAddr; + } + + + public void setNamesrvAddr(String namesrvAddr) { + this.namesrvAddr = namesrvAddr; + } + + + public String getClientIP() { + return clientIP; + } + + + public void setClientIP(String clientIP) { + this.clientIP = clientIP; + } + + + public String getInstanceName() { + return instanceName; + } + + + public void setInstanceName(String instanceName) { + this.instanceName = instanceName; + } + + + public int getClientCallbackExecutorThreads() { + return clientCallbackExecutorThreads; + } + + + public void setClientCallbackExecutorThreads(int clientCallbackExecutorThreads) { + this.clientCallbackExecutorThreads = clientCallbackExecutorThreads; + } + + + public int getPollNameServerInteval() { + return pollNameServerInteval; + } + + + public void setPollNameServerInteval(int pollNameServerInteval) { + this.pollNameServerInteval = pollNameServerInteval; + } + + + public int getHeartbeatBrokerInterval() { + return heartbeatBrokerInterval; + } + + + public void setHeartbeatBrokerInterval(int heartbeatBrokerInterval) { + this.heartbeatBrokerInterval = heartbeatBrokerInterval; + } + + + public int getPersistConsumerOffsetInterval() { + return persistConsumerOffsetInterval; + } + + + public void setPersistConsumerOffsetInterval(int persistConsumerOffsetInterval) { + this.persistConsumerOffsetInterval = persistConsumerOffsetInterval; + } + + + @Override + public String toString() { + return "ClientConfig [namesrvAddr=" + namesrvAddr + ", clientIP=" + clientIP + ", instanceName=" + + instanceName + ", clientCallbackExecutorThreads=" + clientCallbackExecutorThreads + + ", pollNameServerInteval=" + pollNameServerInteval + ", heartbeatBrokerInterval=" + + heartbeatBrokerInterval + ", persistConsumerOffsetInterval=" + + persistConsumerOffsetInterval + "]"; + } +} diff --git a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/MQAdmin.java b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/MQAdmin.java index 31e52ff9..dda677d3 100644 --- a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/MQAdmin.java +++ b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/MQAdmin.java @@ -1,90 +1,101 @@ /** - * $Id: MQAdmin.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.client; import com.alibaba.rocketmq.client.exception.MQBrokerException; import com.alibaba.rocketmq.client.exception.MQClientException; -import com.alibaba.rocketmq.common.MessageExt; -import com.alibaba.rocketmq.common.MessageQueue; -import com.alibaba.rocketmq.common.TopicFilterType; +import com.alibaba.rocketmq.common.message.MessageExt; +import com.alibaba.rocketmq.common.message.MessageQueue; import com.alibaba.rocketmq.remoting.exception.RemotingException; /** - * MQӿ + * MQ管理类接口 * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * @author shijia.wxr + * @since 2013-7-24 */ public interface MQAdmin { /** - * topic + * 创建topic * * @param key - * άԱ + * 请向运维人员申请 * @param newTopic - * Ҫtopic + * 要创建的新topic * @param queueNum - * topic - * @param order - * Ƿϸ˳Ϣ + * 新topic队列数 * @throws MQClientException */ - public void createTopic(final String key, final String newTopic, final int queueNum, - final TopicFilterType topicFilterType, final boolean order) throws MQClientException; + public void createTopic(final String key, final String newTopic, final int queueNum) + throws MQClientException; /** - * ʱѯӦoffsetȷ + * 根据时间查询对应的offset,精确到毫秒
+ * P.S. 当前接口有较多IO开销,请勿频繁调用 * * @param mq - * + * 队列 * @param timestamp - * ʽʱ - * @return ָʱӦoffset + * 毫秒形式时间戳 + * @return 指定时间对应的offset * @throws MQClientException */ public long searchOffset(final MessageQueue mq, final long timestamp) throws MQClientException; /** - * ѯOffset PS: Offset޶ӦϢ1Ϣ + * 向服务器查询队列最大Offset PS: 最大Offset无对应消息,减1有消息 * * @param mq - * - * @return еOffset + * 队列 + * @return 队列的最大Offset * @throws MQClientException */ - public long getMaxOffset(final MessageQueue mq) throws MQClientException; + public long maxOffset(final MessageQueue mq) throws MQClientException; /** - * ѯСOffset PS: СOffsetжӦϢ + * 向服务器查询队列最小Offset PS: 最小Offset有对应消息 * * @param mq - * - * @return еСOffset + * 队列 + * @return 队列的最小Offset * @throws MQClientException */ - public long getMinOffset(final MessageQueue mq) throws MQClientException; + public long minOffset(final MessageQueue mq) throws MQClientException; /** - * ѯбϢӦĴ洢ʱ + * 向服务器查询队列保存的最早消息对应的存储时间 * * @param mq - * - * @return ϢӦĴ洢ʱ䣬ȷ + * 队列 + * @return 最早消息对应的存储时间,精确到毫秒 * @throws MQClientException */ - public long getEarliestMsgStoreTime(final MessageQueue mq) throws MQClientException; + public long earliestMsgStoreTime(final MessageQueue mq) throws MQClientException; /** - * ϢIDӷȡϢ + * 根据消息ID,从服务器获取完整的消息 * * @param msgId - * @return Ϣ + * @return 完整消息 * @throws InterruptedException * @throws MQBrokerException * @throws RemotingException @@ -95,19 +106,19 @@ public MessageExt viewMessage(final String msgId) throws RemotingException, MQBr /** - * ϢKeyѯϢ + * 根据消息Key查询消息 * * @param topic - * Ϣ + * 消息主题 * @param key - * Ϣؼ + * 消息关键词 * @param maxNum - * ѯ + * 查询最大条数 * @param begin - * ʼʱ + * 起始时间戳 * @param end - * ʱ - * @return ѯ + * 结束时间戳 + * @return 查询结果 * @throws MQClientException * @throws InterruptedException */ diff --git a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/MQClientConfig.java b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/MQClientConfig.java deleted file mode 100644 index feb8b26d..00000000 --- a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/MQClientConfig.java +++ /dev/null @@ -1,185 +0,0 @@ -/** - * $Id: MQClientConfig.java 1831 2013-05-16 01:39:51Z shijia.wxr $ - */ -package com.alibaba.rocketmq.client; - -import java.io.File; - -import com.alibaba.rocketmq.remoting.common.RemotingUtil; - - -/** - * ProducerConsumerĹ - * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com - */ -public class MQClientConfig { - private String namesrvAddr = null; - private String logFileName = defaultClientLogFileName(); - private String logLevel = "INFO"; - private String clientIP = RemotingUtil.getLocalAddress(); - private String instanceName = "DEFAULT"; - private int clientCallbackExecutorThreads = 5; - private int pollNameServerInteval = 1000 * 30; - private int heartbeatBrokerInterval = 1000 * 30; - - - public static String defaultClientLogFileName() { - return System.getProperty("user.home") + File.separator + "rocketmqlogs" + File.separator - + "rocketmq_client.log"; - } - - - public String getNamesrvAddr() { - return namesrvAddr; - } - - - public void setNamesrvAddr(String namesrvAddr) { - this.namesrvAddr = namesrvAddr; - } - - - public String getLogFileName() { - return logFileName; - } - - - public void setLogFileName(String logFileName) { - this.logFileName = logFileName; - } - - - public String getLogLevel() { - return logLevel; - } - - - public void setLogLevel(String logLevel) { - this.logLevel = logLevel; - } - - - public String getClientIP() { - return clientIP; - } - - - public void setClientIP(String clientIP) { - this.clientIP = clientIP; - } - - - public String getInstanceName() { - return instanceName; - } - - - public void setInstanceName(String instanceName) { - this.instanceName = instanceName; - } - - - public int getClientCallbackExecutorThreads() { - return clientCallbackExecutorThreads; - } - - - public void setClientCallbackExecutorThreads(int clientCallbackExecutorThreads) { - this.clientCallbackExecutorThreads = clientCallbackExecutorThreads; - } - - - public int getPollNameServerInteval() { - return pollNameServerInteval; - } - - - public void setPollNameServerInteval(int pollNameServerInteval) { - this.pollNameServerInteval = pollNameServerInteval; - } - - - public int getHeartbeatBrokerInterval() { - return heartbeatBrokerInterval; - } - - - public void setHeartbeatBrokerInterval(int heartbeatBrokerInterval) { - this.heartbeatBrokerInterval = heartbeatBrokerInterval; - } - - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + clientCallbackExecutorThreads; - result = prime * result + ((clientIP == null) ? 0 : clientIP.hashCode()); - result = prime * result + heartbeatBrokerInterval; - result = prime * result + ((instanceName == null) ? 0 : instanceName.hashCode()); - result = prime * result + ((logFileName == null) ? 0 : logFileName.hashCode()); - result = prime * result + ((logLevel == null) ? 0 : logLevel.hashCode()); - result = prime * result + ((namesrvAddr == null) ? 0 : namesrvAddr.hashCode()); - result = prime * result + pollNameServerInteval; - return result; - } - - - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - MQClientConfig other = (MQClientConfig) obj; - if (clientCallbackExecutorThreads != other.clientCallbackExecutorThreads) - return false; - if (clientIP == null) { - if (other.clientIP != null) - return false; - } - else if (!clientIP.equals(other.clientIP)) - return false; - if (heartbeatBrokerInterval != other.heartbeatBrokerInterval) - return false; - if (instanceName == null) { - if (other.instanceName != null) - return false; - } - else if (!instanceName.equals(other.instanceName)) - return false; - if (logFileName == null) { - if (other.logFileName != null) - return false; - } - else if (!logFileName.equals(other.logFileName)) - return false; - if (logLevel == null) { - if (other.logLevel != null) - return false; - } - else if (!logLevel.equals(other.logLevel)) - return false; - if (namesrvAddr == null) { - if (other.namesrvAddr != null) - return false; - } - else if (!namesrvAddr.equals(other.namesrvAddr)) - return false; - if (pollNameServerInteval != other.pollNameServerInteval) - return false; - return true; - } - - - @Override - public String toString() { - return "MQClientConfig [namesrvAddr=" + namesrvAddr + ", logFileName=" + logFileName + ", logLevel=" - + logLevel + ", clientIP=" + clientIP + ", instanceName=" + instanceName - + ", clientCallbackExecutorThreads=" + clientCallbackExecutorThreads + ", pollNameServerInteval=" - + pollNameServerInteval + ", heartbeatBrokerInterval=" + heartbeatBrokerInterval + "]"; - } -} diff --git a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/MQHelper.java b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/MQHelper.java new file mode 100644 index 00000000..f69b6ba1 --- /dev/null +++ b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/MQHelper.java @@ -0,0 +1,97 @@ +/** + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.rocketmq.client; + +import java.util.Set; +import java.util.TreeSet; + +import org.slf4j.Logger; + +import com.alibaba.rocketmq.client.consumer.DefaultMQPullConsumer; +import com.alibaba.rocketmq.client.log.ClientLogger; +import com.alibaba.rocketmq.common.message.MessageQueue; +import com.alibaba.rocketmq.common.protocol.heartbeat.MessageModel; + + +/** + * @author shijia.wxr + * @since 2013-11-13 + */ +public class MQHelper { + /** + * 根据时间戳来重置一个订阅组的消费进度 + * + * @param messageModel + * 广播消费还是集群消费 + * @param instanceName + * 实例名称,保持与工作Consumer一致。 + * @param consumerGroup + * 订阅组 + * @param topic + * topic + * @param timestamp + * 时间戳 + * @throws Exception + */ + public static void resetOffsetByTimestamp(// + final MessageModel messageModel,// + final String instanceName,// + final String consumerGroup, // + final String topic, // + final long timestamp) throws Exception { + final Logger log = ClientLogger.getLog(); + + DefaultMQPullConsumer consumer = new DefaultMQPullConsumer(consumerGroup); + consumer.setInstanceName(instanceName); + consumer.setMessageModel(messageModel); + consumer.start(); + + Set mqs = null; + try { + mqs = consumer.fetchSubscribeMessageQueues(topic); + if (mqs != null && !mqs.isEmpty()) { + TreeSet mqsNew = new TreeSet(mqs); + for (MessageQueue mq : mqsNew) { + long offset = consumer.searchOffset(mq, timestamp); + if (offset >= 0) { + consumer.updateConsumeOffset(mq, offset); + log.info("resetOffsetByTimestamp updateConsumeOffset success, {} {} {}", + consumerGroup, offset, mq); + } + } + } + } + catch (Exception e) { + log.warn("resetOffsetByTimestamp Exception", e); + throw e; + } + finally { + if (mqs != null) { + consumer.getDefaultMQPullConsumerImpl().getOffsetStore().persistAll(mqs); + } + consumer.shutdown(); + } + } + + + public static void resetOffsetByTimestamp(// + final MessageModel messageModel,// + final String consumerGroup, // + final String topic, // + final long timestamp) throws Exception { + resetOffsetByTimestamp(messageModel, "DEFAULT", consumerGroup, topic, timestamp); + } +} diff --git a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/QueryResult.java b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/QueryResult.java index 379a7d00..49b88cb2 100644 --- a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/QueryResult.java +++ b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/QueryResult.java @@ -1,17 +1,30 @@ /** - * $Id: QueryResult.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.client; import java.util.List; -import com.alibaba.rocketmq.common.MessageExt; +import com.alibaba.rocketmq.common.message.MessageExt; /** - * ѯϢؽ + * 查询消息返回结果 * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * @author shijia.wxr + * @since 2013-7-24 */ public class QueryResult { private final long indexLastUpdateTimestamp; diff --git a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/Validators.java b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/Validators.java new file mode 100644 index 00000000..94fc60ef --- /dev/null +++ b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/Validators.java @@ -0,0 +1,137 @@ +package com.alibaba.rocketmq.client; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import com.alibaba.rocketmq.client.exception.MQClientException; +import com.alibaba.rocketmq.client.producer.DefaultMQProducer; +import com.alibaba.rocketmq.common.MixAll; +import com.alibaba.rocketmq.common.UtilAll; +import com.alibaba.rocketmq.common.message.Message; + + +/** + * 有效性检查公用类。 + * + * @author manhong.yqd + * @since 2013-8-28 + */ +public class Validators { + public static final String validPatternStr = "^[a-zA-Z0-9_-]+$"; + public static final int CHARACTER_MAX_LENGTH = 255; + + + /** + * 通过正则表达式进行字符匹配 + * + * @param origin + * @param patternStr + * @return + */ + public static boolean regularExpressionMatcher(String origin, String patternStr) { + if (UtilAll.isBlank(origin)) { + return false; + } + if (UtilAll.isBlank(patternStr)) { + return true; + } + Pattern pattern = Pattern.compile(patternStr); + Matcher matcher = pattern.matcher(origin); + return matcher.matches(); + } + + + /** + * 通过正则表达式查找匹配的字符 + * + * @param origin + * @param patternStr + * @return + */ + public static String getGroupWithRegularExpression(String origin, String patternStr) { + Pattern pattern = Pattern.compile(patternStr); + Matcher matcher = pattern.matcher(origin); + while (matcher.find()) { + return matcher.group(0); + } + return null; + } + + + /** + * topic 有效性检查 + * + * @param topic + * @throws com.alibaba.rocketmq.client.exception.MQClientException + */ + public static void checkTopic(String topic) throws MQClientException { + if (UtilAll.isBlank(topic)) { + throw new MQClientException("the specified topic is blank", null); + } + if (!regularExpressionMatcher(topic, validPatternStr)) { + throw new MQClientException(String.format( + "the specified topic[%s] contains illegal characters, allowing only %s", topic, + validPatternStr), null); + } + if (topic.length() > CHARACTER_MAX_LENGTH) { + throw new MQClientException("the specified topic is longer than topic max length 255.", null); + } + + // Topic名字是否与保留字段冲突 + if (topic.equals(MixAll.DEFAULT_TOPIC)) { + throw new MQClientException( + String.format("the topic[%s] is conflict with default topic.", topic), null); + } + } + + + /** + * group 有效性检查 + * + * @param group + * @throws com.alibaba.rocketmq.client.exception.MQClientException + */ + public static void checkGroup(String group) throws MQClientException { + if (UtilAll.isBlank(group)) { + throw new MQClientException("the specified group is blank", null); + } + if (!regularExpressionMatcher(group, validPatternStr)) { + throw new MQClientException(String.format( + "the specified group[%s] contains illegal characters, allowing only %s", group, + validPatternStr), null); + } + if (group.length() > CHARACTER_MAX_LENGTH) { + throw new MQClientException("the specified group is longer than group max length 255.", null); + } + } + + + /** + * message 有效性检查 + * + * @param msg + * @param defaultMQProducer + * @throws com.alibaba.rocketmq.client.exception.MQClientException + */ + public static void checkMessage(Message msg, DefaultMQProducer defaultMQProducer) + throws MQClientException { + if (null == msg) { + throw new MQClientException("the message is null", null); + } + // topic + Validators.checkTopic(msg.getTopic()); + // body + if (null == msg.getBody()) { + throw new MQClientException("the message body is null", null); + } + + if (0 == msg.getBody().length) { + throw new MQClientException("the message body length is zero", null); + } + + if (msg.getBody().length > defaultMQProducer.getMaxMessageSize()) { + throw new MQClientException("the message body size over max value, MAX: " + + defaultMQProducer.getMaxMessageSize(), null); + } + } +} diff --git a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/VirtualEnvUtil.java b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/VirtualEnvUtil.java new file mode 100644 index 00000000..8ac55e72 --- /dev/null +++ b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/VirtualEnvUtil.java @@ -0,0 +1,63 @@ +package com.alibaba.rocketmq.client; + +import com.alibaba.rocketmq.common.UtilAll; + + +/** + * 虚拟环境相关 API 封装 + * + * @author manhong.yqd + * @since 2013-8-26 + */ +public class VirtualEnvUtil { + public static final String VIRTUAL_APPGROUP_PREFIX = "%%PROJECT_%s%%"; + + + /** + * 添加虚拟运行环境相关的projectGroupPrefix + * + * @param origin + * @param projectGroup + * @return + */ + public static String buildWithProjectGroup(String origin, String projectGroup) { + if (!UtilAll.isBlank(projectGroup)) { + String prefix = String.format(VIRTUAL_APPGROUP_PREFIX, projectGroup); + if (!origin.endsWith(prefix)) { + return origin + prefix; + } + else { + return origin; + } + } + else { + return origin; + } + } + + + /** + * 清除虚拟运行环境相关的projectGroupPrefix + * + * @param origin + * @param projectGroup + * @return + */ + public static String clearProjectGroup(String origin, String projectGroup) { + String prefix = String.format(VIRTUAL_APPGROUP_PREFIX, projectGroup); + if (!UtilAll.isBlank(prefix) && origin.endsWith(prefix)) { + return origin.substring(0, origin.lastIndexOf(prefix)); + } + else { + return origin; + } + } + + + public static void main(String[] args) { + String ori = "bbbb"; + String str = buildWithProjectGroup(ori, "AAA"); + System.out.println("build=" + str); + System.out.println("ori=" + clearProjectGroup(str, "AAA")); + } +} diff --git a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/admin/MQAdminExtInner.java b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/admin/MQAdminExtInner.java new file mode 100644 index 00000000..d6b9dd34 --- /dev/null +++ b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/admin/MQAdminExtInner.java @@ -0,0 +1,24 @@ +/** + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.rocketmq.client.admin; + +/** + * @author shijia.wxr + * @since 2013-7-14 + */ +public interface MQAdminExtInner { + +} diff --git a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/consumer/AllocateMessageQueueStrategy.java b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/consumer/AllocateMessageQueueStrategy.java index b6f70f88..8412236a 100644 --- a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/consumer/AllocateMessageQueueStrategy.java +++ b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/consumer/AllocateMessageQueueStrategy.java @@ -1,36 +1,44 @@ /** - * $Id: AllocateMessageQueueStrategy.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.client.consumer; import java.util.List; -import com.alibaba.rocketmq.common.MessageQueue; +import com.alibaba.rocketmq.common.message.MessageQueue; /** - * ConsumerԶ - * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * Consumer队列自动分配策略 * + * @author shijia.wxr + * @since 2013-7-24 */ public interface AllocateMessageQueueStrategy { /** - * з㷨 + * 给当前的ConsumerId分配队列 * - * @param group - * @param topic * @param currentCID - * ǰConsumerId + * 当前ConsumerId * @param mqAll - * ǰTopicжмϣظݣ + * 当前Topic的所有队列集合,无重复数据,且有序 * @param cidAll - * ǰConsumerϣظݣ - * @return ظ + * 当前订阅组的所有Consumer集合,无重复数据,且有序 + * @return 分配结果,无重复数据 */ public List allocate(// - final String group,// - final String topic,// final String currentCID,// final List mqAll,// final List cidAll// diff --git a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/consumer/ConsumeFromWhereOffset.java b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/consumer/ConsumeFromWhereOffset.java deleted file mode 100644 index 7015c39f..00000000 --- a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/consumer/ConsumeFromWhereOffset.java +++ /dev/null @@ -1,29 +0,0 @@ -/** - * $Id: ConsumeFromWhereOffset.java 1831 2013-05-16 01:39:51Z shijia.wxr $ - */ -package com.alibaba.rocketmq.client.consumer; - -/** - * Consumer↑ʼ - * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com - * - */ -public enum ConsumeFromWhereOffset { - /** - * ÿϴμ¼λ㿪ʼѣǵһλ㿪ʼѣʹ - */ - CONSUME_FROM_LAST_OFFSET, - /** - * ÿϴμ¼λ㿪ʼѣǵһСλ㿪ʼѣʱʹ - */ - CONSUME_FROM_LAST_OFFSET_AND_FROM_MIN_WHEN_BOOT_FIRST, - /** - * ÿСλ㿪ʼѣʱʹ - */ - CONSUME_FROM_MIN_OFFSET, - /** - * ÿλ㿪ʼѣʱʹ - */ - CONSUME_FROM_MAX_OFFSET, -} diff --git a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/consumer/ConsumeFromWhichNode.java b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/consumer/ConsumeFromWhichNode.java deleted file mode 100644 index 772468eb..00000000 --- a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/consumer/ConsumeFromWhichNode.java +++ /dev/null @@ -1,29 +0,0 @@ -/** - * $Id: ConsumeFromWhichNode.java 1831 2013-05-16 01:39:51Z shijia.wxr $ - */ -package com.alibaba.rocketmq.client.consumer; - -/** - * ConsumerMasterSlaveϢ - * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com - * - */ -public enum ConsumeFromWhichNode { - /** - * ȴMasterϢMasterڻϢѻתSlave - */ - CONSUME_FROM_MASTER_FIRST, - /** - * ȴSlaveϢSlaveڣתMaster - */ - CONSUME_FROM_SLAVE_FIRST, - /** - * ֻMasterϢ - */ - CONSUME_FROM_MASTER_ONLY, - /** - * ֻSlaveϢ - */ - CONSUME_FROM_SLAVE_ONLY, -} diff --git a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/consumer/DefaultMQPullConsumer.java b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/consumer/DefaultMQPullConsumer.java index 93d385fb..6cdeedde 100644 --- a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/consumer/DefaultMQPullConsumer.java +++ b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/consumer/DefaultMQPullConsumer.java @@ -1,66 +1,82 @@ /** - * $Id: DefaultMQPullConsumer.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.client.consumer; import java.util.HashSet; -import java.util.List; import java.util.Set; -import com.alibaba.rocketmq.client.MQClientConfig; +import com.alibaba.rocketmq.client.ClientConfig; import com.alibaba.rocketmq.client.QueryResult; +import com.alibaba.rocketmq.client.consumer.rebalance.AllocateMessageQueueAveragely; +import com.alibaba.rocketmq.client.consumer.store.OffsetStore; import com.alibaba.rocketmq.client.exception.MQBrokerException; import com.alibaba.rocketmq.client.exception.MQClientException; import com.alibaba.rocketmq.client.impl.consumer.DefaultMQPullConsumerImpl; -import com.alibaba.rocketmq.common.MessageExt; import com.alibaba.rocketmq.common.MixAll; -import com.alibaba.rocketmq.common.MessageQueue; -import com.alibaba.rocketmq.common.TopicFilterType; +import com.alibaba.rocketmq.common.message.MessageExt; +import com.alibaba.rocketmq.common.message.MessageQueue; +import com.alibaba.rocketmq.common.protocol.heartbeat.MessageModel; import com.alibaba.rocketmq.remoting.exception.RemotingException; /** - * Ϣߣ - * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * 消费者,主动拉取方式消费 * + * @author shijia.wxr + * @since 2013-7-24 */ -public class DefaultMQPullConsumer implements MQPullConsumer { - /** - * ͻ˹ã޸ - */ - private MQClientConfig mQClientConfig = new MQClientConfig(); +public class DefaultMQPullConsumer extends ClientConfig implements MQPullConsumer { + protected final transient DefaultMQPullConsumerImpl defaultMQPullConsumerImpl = + new DefaultMQPullConsumerImpl(this); /** - * ͬConsumerΪͬһGroupӦñã֤Ψһ + * 做同样事情的Consumer归为同一个Group,应用必须设置,并保证命名唯一 */ private String consumerGroup = MixAll.DEFAULT_CONSUMER_GROUP; /** - * ѯģʽConsumerBrokerʱ䣬޸ + * 长轮询模式,Consumer连接在Broker挂起最长时间,不建议修改 */ private long brokerSuspendMaxTimeMillis = 1000 * 20; /** - * ѯģʽConsumerʱʱ䣨ҪbrokerSuspendMaxTimeMillis޸ + * 长轮询模式,Consumer超时时间(必须要大于brokerSuspendMaxTimeMillis),不建议修改 */ private long consumerTimeoutMillisWhenSuspend = 1000 * 30; /** - * ģʽConsumerʱʱ䣬޸ + * 非阻塞拉模式,Consumer超时时间,不建议修改 */ private long consumerPullTimeoutMillis = 1000 * 10; /** - * ConsumerMasterSlaveϢ + * 集群消费/广播消费 */ - private ConsumeFromWhichNode consumeFromWhichNode = ConsumeFromWhichNode.CONSUME_FROM_MASTER_FIRST; + private MessageModel messageModel = MessageModel.BROADCASTING; /** - * б仯 + * 队列变化监听器 */ private MessageQueueListener messageQueueListener; /** - * ҪЩTopicĶб仯 + * Offset存储,系统会根据客户端配置自动创建相应的实现,如果应用配置了,则以应用配置的为主 + */ + private OffsetStore offsetStore; + /** + * 需要监听哪些Topic的队列变化 */ private Set registerTopics = new HashSet(); - - private final DefaultMQPullConsumerImpl defaultMQPullConsumerImpl = new DefaultMQPullConsumerImpl( - this); + /** + * 队列分配算法,应用可重写 + */ + private AllocateMessageQueueStrategy allocateMessageQueueStrategy = new AllocateMessageQueueAveragely(); public DefaultMQPullConsumer() { @@ -73,9 +89,8 @@ public DefaultMQPullConsumer(final String consumerGroup) { @Override - public void createTopic(String key, String newTopic, int queueNum, TopicFilterType topicFilterType, - boolean order) throws MQClientException { - this.defaultMQPullConsumerImpl.createTopic(key, newTopic, queueNum, topicFilterType, order); + public void createTopic(String key, String newTopic, int queueNum) throws MQClientException { + this.defaultMQPullConsumerImpl.createTopic(key, newTopic, queueNum); } @@ -86,20 +101,20 @@ public long searchOffset(MessageQueue mq, long timestamp) throws MQClientExcepti @Override - public long getMaxOffset(MessageQueue mq) throws MQClientException { - return this.defaultMQPullConsumerImpl.getMaxOffset(mq); + public long maxOffset(MessageQueue mq) throws MQClientException { + return this.defaultMQPullConsumerImpl.maxOffset(mq); } @Override - public long getMinOffset(MessageQueue mq) throws MQClientException { - return this.defaultMQPullConsumerImpl.getMinOffset(mq); + public long minOffset(MessageQueue mq) throws MQClientException { + return this.defaultMQPullConsumerImpl.minOffset(mq); } @Override - public long getEarliestMsgStoreTime(MessageQueue mq) throws MQClientException { - return this.defaultMQPullConsumerImpl.getEarliestMsgStoreTime(mq); + public long earliestMsgStoreTime(MessageQueue mq) throws MQClientException { + return this.defaultMQPullConsumerImpl.earliestMsgStoreTime(mq); } @@ -117,165 +132,179 @@ public QueryResult queryMessage(String topic, String key, int maxNum, long begin } - @Override - public void start() throws MQClientException { - this.defaultMQPullConsumerImpl.start(); + public AllocateMessageQueueStrategy getAllocateMessageQueueStrategy() { + return allocateMessageQueueStrategy; } - @Override - public void shutdown() { - this.defaultMQPullConsumerImpl.shutdown(); + public void setAllocateMessageQueueStrategy(AllocateMessageQueueStrategy allocateMessageQueueStrategy) { + this.allocateMessageQueueStrategy = allocateMessageQueueStrategy; } - @Override - public void registerMessageQueueListener(String topic, MessageQueueListener listener) { - synchronized (this.registerTopics) { - this.registerTopics.add(topic); - if (listener != null) { - this.messageQueueListener = listener; - } - } + public long getBrokerSuspendMaxTimeMillis() { + return brokerSuspendMaxTimeMillis; } - @Override - public PullResult pull(MessageQueue mq, String subExpression, long offset, int maxNums) - throws MQClientException, RemotingException, MQBrokerException, InterruptedException { - return this.defaultMQPullConsumerImpl.pull(mq, subExpression, offset, maxNums); + public void setBrokerSuspendMaxTimeMillis(long brokerSuspendMaxTimeMillis) { + this.brokerSuspendMaxTimeMillis = brokerSuspendMaxTimeMillis; } - @Override - public PullResult pullBlockIfNotFound(MessageQueue mq, String subExpression, long offset, int maxNums) - throws MQClientException, RemotingException, MQBrokerException, InterruptedException { - return this.defaultMQPullConsumerImpl.pullBlockIfNotFound(mq, subExpression, offset, maxNums); + public String getConsumerGroup() { + return consumerGroup; } - @Override - public void pull(MessageQueue mq, String subExpression, long offset, int maxNums, PullCallback pullCallback) - throws MQClientException, RemotingException, InterruptedException { - this.defaultMQPullConsumerImpl.pull(mq, subExpression, offset, maxNums, pullCallback); + public void setConsumerGroup(String consumerGroup) { + this.consumerGroup = consumerGroup; } - @Override - public void pullBlockIfNotFound(MessageQueue mq, String subExpression, long offset, int maxNums, - PullCallback pullCallback) throws MQClientException, RemotingException, InterruptedException { - this.defaultMQPullConsumerImpl.pullBlockIfNotFound(mq, subExpression, offset, maxNums, pullCallback); + public long getConsumerPullTimeoutMillis() { + return consumerPullTimeoutMillis; } - @Override - public void updateConsumeOffset(MessageQueue mq, long offset) throws RemotingException, MQBrokerException, - InterruptedException, MQClientException { - this.defaultMQPullConsumerImpl.updateConsumeOffset(mq, offset); + public void setConsumerPullTimeoutMillis(long consumerPullTimeoutMillis) { + this.consumerPullTimeoutMillis = consumerPullTimeoutMillis; } - @Override - public long fetchConsumeOffset(MessageQueue mq) throws RemotingException, MQBrokerException, - InterruptedException, MQClientException { - return this.defaultMQPullConsumerImpl.fetchConsumeOffset(mq); + public long getConsumerTimeoutMillisWhenSuspend() { + return consumerTimeoutMillisWhenSuspend; } - @Override - public List fetchMessageQueuesInBalance(String topic) { - return this.defaultMQPullConsumerImpl.fetchMessageQueuesInBalance(topic); + public void setConsumerTimeoutMillisWhenSuspend(long consumerTimeoutMillisWhenSuspend) { + this.consumerTimeoutMillisWhenSuspend = consumerTimeoutMillisWhenSuspend; } - @Override - public List fetchSubscribeMessageQueues(String topic) throws MQClientException { - return this.defaultMQPullConsumerImpl.fetchSubscribeMessageQueues(topic); + public MessageModel getMessageModel() { + return messageModel; } - public MQClientConfig getMQClientConfig() { - return mQClientConfig; + public void setMessageModel(MessageModel messageModel) { + this.messageModel = messageModel; } - public void setMQClientConfig(MQClientConfig mQClientConfig) { - this.mQClientConfig = mQClientConfig; + public MessageQueueListener getMessageQueueListener() { + return messageQueueListener; } - public long getBrokerSuspendMaxTimeMillis() { - return brokerSuspendMaxTimeMillis; + public void setMessageQueueListener(MessageQueueListener messageQueueListener) { + this.messageQueueListener = messageQueueListener; } - public void setBrokerSuspendMaxTimeMillis(long brokerSuspendMaxTimeMillis) { - this.brokerSuspendMaxTimeMillis = brokerSuspendMaxTimeMillis; + public Set getRegisterTopics() { + return registerTopics; } - public long getConsumerTimeoutMillisWhenSuspend() { - return consumerTimeoutMillisWhenSuspend; + public void setRegisterTopics(Set registerTopics) { + this.registerTopics = registerTopics; } - public void setConsumerTimeoutMillisWhenSuspend(long consumerTimeoutMillisWhenSuspend) { - this.consumerTimeoutMillisWhenSuspend = consumerTimeoutMillisWhenSuspend; + @Override + public void sendMessageBack(MessageExt msg, int delayLevel) throws RemotingException, MQBrokerException, + InterruptedException, MQClientException { + this.defaultMQPullConsumerImpl.sendMessageBack(msg, delayLevel); } - public long getConsumerPullTimeoutMillis() { - return consumerPullTimeoutMillis; + @Override + public Set fetchSubscribeMessageQueues(String topic) throws MQClientException { + return this.defaultMQPullConsumerImpl.fetchSubscribeMessageQueues(topic); } - public void setConsumerPullTimeoutMillis(long consumerPullTimeoutMillis) { - this.consumerPullTimeoutMillis = consumerPullTimeoutMillis; + @Override + public void start() throws MQClientException { + this.defaultMQPullConsumerImpl.start(); } - public String getConsumerGroup() { - return consumerGroup; + @Override + public void shutdown() { + this.defaultMQPullConsumerImpl.shutdown(); } - public void setConsumerGroup(String consumerGroup) { - this.consumerGroup = consumerGroup; + @Override + public void registerMessageQueueListener(String topic, MessageQueueListener listener) { + synchronized (this.registerTopics) { + this.registerTopics.add(topic); + if (listener != null) { + this.messageQueueListener = listener; + } + } } - public MessageQueueListener getMessageQueueListener() { - return messageQueueListener; + @Override + public PullResult pull(MessageQueue mq, String subExpression, long offset, int maxNums) + throws MQClientException, RemotingException, MQBrokerException, InterruptedException { + return this.defaultMQPullConsumerImpl.pull(mq, subExpression, offset, maxNums); } - public void setMessageQueueListener(MessageQueueListener messageQueueListener) { - this.messageQueueListener = messageQueueListener; + @Override + public void pull(MessageQueue mq, String subExpression, long offset, int maxNums, + PullCallback pullCallback) throws MQClientException, RemotingException, InterruptedException { + this.defaultMQPullConsumerImpl.pull(mq, subExpression, offset, maxNums, pullCallback); } - public Set getRegisterTopics() { - return registerTopics; + @Override + public PullResult pullBlockIfNotFound(MessageQueue mq, String subExpression, long offset, int maxNums) + throws MQClientException, RemotingException, MQBrokerException, InterruptedException { + return this.defaultMQPullConsumerImpl.pullBlockIfNotFound(mq, subExpression, offset, maxNums); } - public void setRegisterTopics(Set registerTopics) { - this.registerTopics = registerTopics; + @Override + public void pullBlockIfNotFound(MessageQueue mq, String subExpression, long offset, int maxNums, + PullCallback pullCallback) throws MQClientException, RemotingException, InterruptedException { + this.defaultMQPullConsumerImpl.pullBlockIfNotFound(mq, subExpression, offset, maxNums, pullCallback); + } + + + @Override + public void updateConsumeOffset(MessageQueue mq, long offset) throws MQClientException { + this.defaultMQPullConsumerImpl.updateConsumeOffset(mq, offset); } @Override - public void sendMessageBack(MessageExt msg, MessageQueue mq, int delayLevel) { - // TODO + public long fetchConsumeOffset(MessageQueue mq, boolean fromStore) throws MQClientException { + return this.defaultMQPullConsumerImpl.fetchConsumeOffset(mq, fromStore); + } + + + @Override + public Set fetchMessageQueuesInBalance(String topic) throws MQClientException { + return this.defaultMQPullConsumerImpl.fetchMessageQueuesInBalance(topic); + } + + + public OffsetStore getOffsetStore() { + return offsetStore; } - public ConsumeFromWhichNode getConsumeFromWhichNode() { - return consumeFromWhichNode; + public void setOffsetStore(OffsetStore offsetStore) { + this.offsetStore = offsetStore; } - public void setConsumeFromWhichNode(ConsumeFromWhichNode consumeFromWhichNode) { - this.consumeFromWhichNode = consumeFromWhichNode; + public DefaultMQPullConsumerImpl getDefaultMQPullConsumerImpl() { + return defaultMQPullConsumerImpl; } } diff --git a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/consumer/DefaultMQPushConsumer.java b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/consumer/DefaultMQPushConsumer.java index 8352bdf4..4e02f352 100644 --- a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/consumer/DefaultMQPushConsumer.java +++ b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/consumer/DefaultMQPushConsumer.java @@ -1,76 +1,120 @@ /** - * $Id: DefaultMQPushConsumer.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.client.consumer; import java.util.HashMap; -import java.util.List; import java.util.Map; +import java.util.Set; -import com.alibaba.rocketmq.client.MQClientConfig; +import com.alibaba.rocketmq.client.ClientConfig; import com.alibaba.rocketmq.client.QueryResult; import com.alibaba.rocketmq.client.consumer.listener.MessageListener; -import com.alibaba.rocketmq.client.consumer.loadbalance.AllocateMessageQueueAveragely; +import com.alibaba.rocketmq.client.consumer.rebalance.AllocateMessageQueueAveragely; +import com.alibaba.rocketmq.client.consumer.store.OffsetStore; import com.alibaba.rocketmq.client.exception.MQBrokerException; import com.alibaba.rocketmq.client.exception.MQClientException; import com.alibaba.rocketmq.client.impl.consumer.DefaultMQPushConsumerImpl; -import com.alibaba.rocketmq.common.MessageExt; import com.alibaba.rocketmq.common.MixAll; -import com.alibaba.rocketmq.common.MessageQueue; -import com.alibaba.rocketmq.common.TopicFilterType; +import com.alibaba.rocketmq.common.UtilAll; +import com.alibaba.rocketmq.common.consumer.ConsumeFromWhere; +import com.alibaba.rocketmq.common.message.MessageExt; +import com.alibaba.rocketmq.common.message.MessageQueue; +import com.alibaba.rocketmq.common.protocol.heartbeat.MessageModel; import com.alibaba.rocketmq.remoting.exception.RemotingException; /** - * Consumer - * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * 类似于Broker Push消息到Consumer方式,但实际仍然是Consumer内部后台从Broker Pull消息
+ * 采用长轮询方式拉消息,实时性同push方式一致,且不会无谓的拉消息导致Broker、Consumer压力增大 * + * @author shijia.wxr + * @since 2013-7-24 */ -public class DefaultMQPushConsumer implements MQPushConsumer { +public class DefaultMQPushConsumer extends ClientConfig implements MQPushConsumer { + protected final transient DefaultMQPushConsumerImpl defaultMQPushConsumerImpl = + new DefaultMQPushConsumerImpl(this); /** - * ͻ˹ã޸ + * 做同样事情的Consumer归为同一个Group,应用必须设置,并保证命名唯一 */ - private MQClientConfig mQClientConfig = new MQClientConfig(); + private String consumerGroup = MixAll.DEFAULT_CONSUMER_GROUP; /** - * ͬConsumerΪͬһGroupӦñã֤Ψһ + * 集群消费/广播消费 */ - private String consumerGroup = MixAll.DEFAULT_CONSUMER_GROUP; + private MessageModel messageModel = MessageModel.CLUSTERING; /** - * ConsumerMasterSlaveϢ + * Consumer第一次启动时,从哪里开始消费 */ - private ConsumeFromWhichNode consumeFromWhichNode = ConsumeFromWhichNode.CONSUME_FROM_MASTER_FIRST; + private ConsumeFromWhere consumeFromWhere = ConsumeFromWhere.CONSUME_FROM_LAST_OFFSET; /** - * Consumerʱ↑ʼ + * Consumer第一次启动时,如果回溯消费,默认回溯到哪个时间点,数据格式如下,时间精度秒:
+ * 20131223171201
+ * 表示2013年12月23日17点12分01秒
+ * 默认回溯到相对启动时间的半小时前 */ - private ConsumeFromWhereOffset consumeFromWhereOffset = ConsumeFromWhereOffset.CONSUME_FROM_LAST_OFFSET; + private String consumeTimestamp = UtilAll.timeMillisToHumanString3(System.currentTimeMillis() + - (1000 * 60 * 30)); /** - * з㷨Ӧÿд + * 队列分配算法,应用可重写 */ private AllocateMessageQueueStrategy allocateMessageQueueStrategy = new AllocateMessageQueueAveragely(); /** - * Ĺϵ + * 订阅关系 */ private Map subscription = new HashMap(); /** - * Ϣ + * 消息监听器 */ private MessageListener messageListener; /** - * Ϣ߳ + * Offset存储,系统会根据客户端配置自动创建相应的实现,如果应用配置了,则以应用配置的为主 */ - private int consumeThreadCount = 10; + private OffsetStore offsetStore; /** - * ͬһвѵȣ˳ѷʽ£˲Ч + * 消费消息线程,最小数目 */ - private int consumeConcurrentlyMaxSpan = 1000; + private int consumeThreadMin = 20; /** - * һϢ + * 消费消息线程,最大数目 + */ + private int consumeThreadMax = 20; + /** + * 同一队列并行消费的最大跨度,顺序消费方式情况下,此参数无效 + */ + private int consumeConcurrentlyMaxSpan = 2000; + /** + * 本地队列消息数超过此阀值,开始流控 + */ + private int pullThresholdForQueue = 1000; + /** + * 拉消息间隔,如果为了降低拉取速度,可以设置大于0的值 + */ + private long pullInterval = 0; + /** + * 消费一批消息,最大数 */ private int consumeMessageBatchMaxSize = 1; + /** + * 拉消息,一次拉多少条 + */ + private int pullBatchSize = 32; - private final DefaultMQPushConsumerImpl defaultMQPushConsumerImpl = - new DefaultMQPushConsumerImpl(this); + /** + * 是否每次拉消息时,都上传订阅关系 + */ + private boolean postSubscriptionWhenPull = false; public DefaultMQPushConsumer() { @@ -84,115 +128,273 @@ public DefaultMQPushConsumer(final String consumerGroup) { @Override - public void sendMessageBack(MessageExt msg, MessageQueue mq, int delayLevel) { - // TODO Auto-generated method stub - } - - - @Override - public void createTopic(String key, String newTopic, int queueNum, TopicFilterType topicFilterType, - boolean order) throws MQClientException { - // TODO Auto-generated method stub - + public void createTopic(String key, String newTopic, int queueNum) throws MQClientException { + this.defaultMQPushConsumerImpl.createTopic(key, newTopic, queueNum); } @Override public long searchOffset(MessageQueue mq, long timestamp) throws MQClientException { - // TODO Auto-generated method stub - return 0; + return this.defaultMQPushConsumerImpl.searchOffset(mq, timestamp); } @Override - public long getMaxOffset(MessageQueue mq) throws MQClientException { - // TODO Auto-generated method stub - return 0; + public long maxOffset(MessageQueue mq) throws MQClientException { + return this.defaultMQPushConsumerImpl.maxOffset(mq); } @Override - public long getMinOffset(MessageQueue mq) throws MQClientException { - // TODO Auto-generated method stub - return 0; + public long minOffset(MessageQueue mq) throws MQClientException { + return this.defaultMQPushConsumerImpl.minOffset(mq); } @Override - public long getEarliestMsgStoreTime(MessageQueue mq) throws MQClientException { - // TODO Auto-generated method stub - return 0; + public long earliestMsgStoreTime(MessageQueue mq) throws MQClientException { + return this.defaultMQPushConsumerImpl.earliestMsgStoreTime(mq); } @Override public MessageExt viewMessage(String msgId) throws RemotingException, MQBrokerException, InterruptedException, MQClientException { - // TODO Auto-generated method stub - return null; + return this.defaultMQPushConsumerImpl.viewMessage(msgId); } @Override public QueryResult queryMessage(String topic, String key, int maxNum, long begin, long end) throws MQClientException, InterruptedException { - // TODO Auto-generated method stub - return null; + return this.defaultMQPushConsumerImpl.queryMessage(topic, key, maxNum, begin, end); } - @Override - public void start() { - // TODO Auto-generated method stub + public AllocateMessageQueueStrategy getAllocateMessageQueueStrategy() { + return allocateMessageQueueStrategy; + } + + + public void setAllocateMessageQueueStrategy(AllocateMessageQueueStrategy allocateMessageQueueStrategy) { + this.allocateMessageQueueStrategy = allocateMessageQueueStrategy; + } + + + public int getConsumeConcurrentlyMaxSpan() { + return consumeConcurrentlyMaxSpan; + } + + + public void setConsumeConcurrentlyMaxSpan(int consumeConcurrentlyMaxSpan) { + this.consumeConcurrentlyMaxSpan = consumeConcurrentlyMaxSpan; + } + + + public ConsumeFromWhere getConsumeFromWhere() { + return consumeFromWhere; + } + + + public void setConsumeFromWhere(ConsumeFromWhere consumeFromWhere) { + this.consumeFromWhere = consumeFromWhere; + } + + + public int getConsumeMessageBatchMaxSize() { + return consumeMessageBatchMaxSize; + } + + + public void setConsumeMessageBatchMaxSize(int consumeMessageBatchMaxSize) { + this.consumeMessageBatchMaxSize = consumeMessageBatchMaxSize; + } + + + public String getConsumerGroup() { + return consumerGroup; + } + + + public void setConsumerGroup(String consumerGroup) { + this.consumerGroup = consumerGroup; + } + + + public int getConsumeThreadMax() { + return consumeThreadMax; + } + + + public void setConsumeThreadMax(int consumeThreadMax) { + this.consumeThreadMax = consumeThreadMax; + } + + + public int getConsumeThreadMin() { + return consumeThreadMin; + } + + + public void setConsumeThreadMin(int consumeThreadMin) { + this.consumeThreadMin = consumeThreadMin; + } + + + public DefaultMQPushConsumerImpl getDefaultMQPushConsumerImpl() { + return defaultMQPushConsumerImpl; + } + + public MessageListener getMessageListener() { + return messageListener; + } + + + public void setMessageListener(MessageListener messageListener) { + this.messageListener = messageListener; + } + + + public MessageModel getMessageModel() { + return messageModel; + } + + + public void setMessageModel(MessageModel messageModel) { + this.messageModel = messageModel; + } + + + public int getPullBatchSize() { + return pullBatchSize; + } + + + public void setPullBatchSize(int pullBatchSize) { + this.pullBatchSize = pullBatchSize; + } + + + public long getPullInterval() { + return pullInterval; + } + + + public void setPullInterval(long pullInterval) { + this.pullInterval = pullInterval; + } + + + public int getPullThresholdForQueue() { + return pullThresholdForQueue; + } + + + public void setPullThresholdForQueue(int pullThresholdForQueue) { + this.pullThresholdForQueue = pullThresholdForQueue; + } + + + public Map getSubscription() { + return subscription; + } + + + public void setSubscription(Map subscription) { + this.subscription = subscription; } @Override - public void shutdown() { - // TODO Auto-generated method stub + public void sendMessageBack(MessageExt msg, int delayLevel) throws RemotingException, MQBrokerException, + InterruptedException, MQClientException { + this.defaultMQPushConsumerImpl.sendMessageBack(msg, delayLevel); + } + + @Override + public Set fetchSubscribeMessageQueues(String topic) throws MQClientException { + return this.defaultMQPushConsumerImpl.fetchSubscribeMessageQueues(topic); } @Override - public void registerMessageListener(MessageListener messageListener) { - // TODO Auto-generated method stub + public void start() throws MQClientException { + this.defaultMQPushConsumerImpl.start(); + } + + @Override + public void shutdown() { + this.defaultMQPushConsumerImpl.shutdown(); } @Override - public void subscribe(String topic, String subExpression) { - // TODO Auto-generated method stub + public void registerMessageListener(MessageListener messageListener) { + this.messageListener = messageListener; + this.defaultMQPushConsumerImpl.registerMessageListener(messageListener); + } + + @Override + public void subscribe(String topic, String subExpression) throws MQClientException { + this.defaultMQPushConsumerImpl.subscribe(topic, subExpression); } @Override public void unsubscribe(String topic) { - // TODO Auto-generated method stub + this.defaultMQPushConsumerImpl.unsubscribe(topic); + } + + @Override + public void updateCorePoolSize(int corePoolSize) { + this.defaultMQPushConsumerImpl.updateCorePoolSize(corePoolSize); } @Override public void suspend() { - // TODO Auto-generated method stub - + this.defaultMQPushConsumerImpl.suspend(); } @Override public void resume() { - // TODO Auto-generated method stub + this.defaultMQPushConsumerImpl.resume(); + } + + public OffsetStore getOffsetStore() { + return offsetStore; } - @Override - public List fetchSubscribeMessageQueues(String topic) throws MQClientException { - // TODO Auto-generated method stub - return null; + public void setOffsetStore(OffsetStore offsetStore) { + this.offsetStore = offsetStore; + } + + + public String getConsumeTimestamp() { + return consumeTimestamp; + } + + + public void setConsumeTimestamp(String consumeTimestamp) { + this.consumeTimestamp = consumeTimestamp; + } + + + public boolean isPostSubscriptionWhenPull() { + return postSubscriptionWhenPull; } + + + public void setPostSubscriptionWhenPull(boolean postSubscriptionWhenPull) { + this.postSubscriptionWhenPull = postSubscriptionWhenPull; + } + } diff --git a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/consumer/MQConsumer.java b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/consumer/MQConsumer.java index 7e8762a9..3302d7e8 100644 --- a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/consumer/MQConsumer.java +++ b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/consumer/MQConsumer.java @@ -1,42 +1,62 @@ /** - * $Id: MQConsumer.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.client.consumer; -import java.util.List; +import java.util.Set; import com.alibaba.rocketmq.client.MQAdmin; +import com.alibaba.rocketmq.client.exception.MQBrokerException; import com.alibaba.rocketmq.client.exception.MQClientException; -import com.alibaba.rocketmq.common.MessageExt; -import com.alibaba.rocketmq.common.MessageQueue; +import com.alibaba.rocketmq.common.message.MessageExt; +import com.alibaba.rocketmq.common.message.MessageQueue; +import com.alibaba.rocketmq.remoting.exception.RemotingException; /** - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * Consumer接口 * + * @author shijia.wxr + * @since 2013-7-24 */ public interface MQConsumer extends MQAdmin { /** - * ConsumerʧܵϢѡ·صˣʱ
- * ȳԽϢصϢ֮ǰ洢ʱֻϢOffsetϢ岻ͣռ
- * ʧܣԶԷʱϢҲᴫ
- * شȥϢֻᱻǰConsumer Groupѡ + * Consumer消费失败的消息可以选择重新发回到服务器端,并延时消费
+ * 会首先尝试将消息发回到消息之前存储的主机,此时只传送消息Offset,消息体不传送,不会占用网络带宽
+ * 如果发送失败,会自动重试发往其他主机,此时消息体也会传送
+ * 重传回去的消息只会被当前Consumer Group消费。 * * @param msg - * @param mq * @param delayLevel + * @throws InterruptedException + * @throws MQBrokerException + * @throws RemotingException + * @throws MQClientException */ - public void sendMessageBack(final MessageExt msg, final MessageQueue mq, final int delayLevel); + public void sendMessageBack(final MessageExt msg, final int delayLevel) throws RemotingException, + MQBrokerException, InterruptedException, MQClientException; /** - * topicȡӦMessageQueueǿɱĵĶ + * 根据topic获取对应的MessageQueue,是可被订阅的队列
+ * P.S 从Consumer Cache中拿数据,可以频繁调用。Cache中数据大约30秒更新一次 * * @param topic - * ϢTopic - * @return ضм + * 消息Topic + * @return 返回队列集合 * @throws MQClientException */ - public List fetchSubscribeMessageQueues(final String topic) throws MQClientException; - + public Set fetchSubscribeMessageQueues(final String topic) throws MQClientException; } diff --git a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/consumer/MQPullConsumer.java b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/consumer/MQPullConsumer.java index 3f40f598..ae8ffe09 100644 --- a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/consumer/MQPullConsumer.java +++ b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/consumer/MQPullConsumer.java @@ -1,24 +1,37 @@ /** - * $Id: MQPullConsumer.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.client.consumer; -import java.util.List; +import java.util.Set; import com.alibaba.rocketmq.client.exception.MQBrokerException; import com.alibaba.rocketmq.client.exception.MQClientException; -import com.alibaba.rocketmq.common.MessageQueue; +import com.alibaba.rocketmq.common.message.MessageQueue; import com.alibaba.rocketmq.remoting.exception.RemotingException; /** - * ߣʽ + * 消费者,主动方式消费 * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * @author shijia.wxr + * @since 2013-7-24 */ public interface MQPullConsumer extends MQConsumer { /** - * + * 启动服务 * * @throws MQClientException */ @@ -26,73 +39,73 @@ public interface MQPullConsumer extends MQConsumer { /** - * رշ + * 关闭服务 */ public void shutdown(); /** - * עб仯listener + * 注册监听队列变化的listener对象 * * @param topic * @param listener - * һ仯ͻ˻صlistener + * 一旦发生变化,客户端会主动回调listener对象 */ public void registerMessageQueueListener(final String topic, final MessageQueueListener listener); /** - * ָУȡϢʹûϢҲ̷ + * 指定队列,主动拉取消息,即使没有消息,也立刻返回 * * @param mq - * ָҪȡĶ + * 指定具体要拉取的队列 * @param subExpression - * Ĺ˱ʽַbrokerݴ˱ʽйˡ
+ * 订阅过滤表达式字符串,broker依据此表达式进行过滤。目前只支持或运算
* eg: "tag1 || tag2 || tag3"
- * "tag1 || (tag2 && tag3)"
- * subExpression=null, ʾȫ + * 如果subExpression等于null或者*,则表示全部订阅 * @param offset - * ָĸλÿʼȡ + * 从指定队列哪个位置开始拉取 * @param maxNums - * һȡ - * @return μPullResult + * 一次最多拉取条数 + * @return 参见PullResult * @throws MQClientException * @throws InterruptedException * @throws MQBrokerException * @throws RemotingException */ - public PullResult pull(final MessageQueue mq, final String subExpression, final long offset, final int maxNums) - throws MQClientException, RemotingException, MQBrokerException, InterruptedException; + public PullResult pull(final MessageQueue mq, final String subExpression, final long offset, + final int maxNums) throws MQClientException, RemotingException, MQBrokerException, + InterruptedException; public void pull(final MessageQueue mq, final String subExpression, final long offset, final int maxNums, - final PullCallback pullCallback) throws MQClientException, RemotingException, InterruptedException; + final PullCallback pullCallback) throws MQClientException, RemotingException, + InterruptedException; /** - * ָУȡϢûϢbrokerһʱٷأʱã
- * brokerڼ䣬Ϣ̽Ϣ + * 指定队列,主动拉取消息,如果没有消息,则broker阻塞一段时间再返回(时间可配置)
+ * broker阻塞期间,如果有消息,则立刻将消息返回 * * @param mq - * ָҪȡĶ + * 指定具体要拉取的队列 * @param subExpression - * Ĺ˱ʽַbrokerݴ˱ʽйˡ
+ * 订阅过滤表达式字符串,broker依据此表达式进行过滤。目前只支持或运算
* eg: "tag1 || tag2 || tag3"
- * "tag1 || (tag2 && tag3)"
- * subExpression=null, ʾȫ + * 如果subExpression等于null或者*,则表示全部订阅 * @param offset - * ָĸλÿʼȡ + * 从指定队列哪个位置开始拉取 * @param maxNums - * һȡ - * @return μPullResult + * 一次最多拉取条数 + * @return 参见PullResult * @throws InterruptedException * @throws MQBrokerException * @throws RemotingException * @throws MQClientException */ - public PullResult pullBlockIfNotFound(final MessageQueue mq, final String subExpression, final long offset, - final int maxNums) throws MQClientException, RemotingException, MQBrokerException, - InterruptedException; + public PullResult pullBlockIfNotFound(final MessageQueue mq, final String subExpression, + final long offset, final int maxNums) throws MQClientException, RemotingException, + MQBrokerException, InterruptedException; public void pullBlockIfNotFound(final MessageQueue mq, final String subExpression, final long offset, @@ -100,21 +113,38 @@ public void pullBlockIfNotFound(final MessageQueue mq, final String subExpressio InterruptedException; - public void updateConsumeOffset(final MessageQueue mq, final long offset) throws RemotingException, - MQBrokerException, InterruptedException, MQClientException; + /** + * 更新消费进度
+ * 只是更新Consumer缓存中的数据,如果是广播模式,则定时更新到本地存储
+ * 如果是集群模式,则定时更新到远端Broker
+ *

+ * P.S. 可频繁调用,无性能开销 + * + * @param mq + * @param offset + * @throws MQClientException + */ + public void updateConsumeOffset(final MessageQueue mq, final long offset) throws MQClientException; - public long fetchConsumeOffset(final MessageQueue mq) throws RemotingException, MQBrokerException, - InterruptedException, MQClientException; + /** + * 获取消费进度,返回-1表示出错 + * + * @param mq + * @param fromStore + * @return + * @throws MQClientException + */ + public long fetchConsumeOffset(final MessageQueue mq, final boolean fromStore) throws MQClientException; /** - * topicȡMessageQueueԾⷽʽڶԱ֮ + * 根据topic获取MessageQueue,以均衡方式在组内多个成员之间分配 * * @param topic - * ϢTopic - * @return ɹ ضм ʧ null - * + * 消息Topic + * @return 返回队列集合 + * @throws MQClientException */ - public List fetchMessageQueuesInBalance(final String topic); + public Set fetchMessageQueuesInBalance(final String topic) throws MQClientException; } diff --git a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/consumer/MQPushConsumer.java b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/consumer/MQPushConsumer.java index 38d73324..6bea7d22 100644 --- a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/consumer/MQPushConsumer.java +++ b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/consumer/MQPushConsumer.java @@ -1,30 +1,48 @@ /** - * $Id: MQPushConsumer.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.client.consumer; import com.alibaba.rocketmq.client.consumer.listener.MessageListener; +import com.alibaba.rocketmq.client.exception.MQClientException; + /** - * ߣʽ + * 消费者,被动方式消费 * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * @author shijia.wxr + * @since 2013-7-24 */ public interface MQPushConsumer extends MQConsumer { /** - * 񣬵֮ǰȷregisterMessageListenersubscribeѾ + * 启动服务,调用之前确保registerMessageListener与subscribe都已经调用
+ * 或者已经通过Spring注入了相关配置 + * + * @throws MQClientException */ - public void start(); + public void start() throws MQClientException; /** - * رշ + * 关闭服务,一旦关闭,此对象将不可用 */ public void shutdown(); /** - * עϢһConsumerֻһ + * 注册消息监听器,一个Consumer只能有一个监听器 * * @param messageListener */ @@ -32,38 +50,46 @@ public interface MQPushConsumer extends MQConsumer { /** - * ϢԵöIJͬTopicҲɸ֮ǰTopicĶĹ˱ʽ + * 订阅消息,方法可以调用多次来订阅不同的Topic,也可覆盖之前Topic的订阅过滤表达式 * * @param topic - * Ϣ + * 消息主题 * @param subExpression - * Ĺ˱ʽַbrokerݴ˱ʽйˡ
+ * 订阅过滤表达式字符串,broker依据此表达式进行过滤。目前只支持或运算
* eg: "tag1 || tag2 || tag3"
- * "tag1 || (tag2 && tag3)"
- * subExpression=null, ʾȫ + * 如果subExpression等于null或者*,则表示全部订阅 * @param listener - * Ϣص + * 消息回调监听器 + * @throws MQClientException */ - public void subscribe(final String topic, final String subExpression); + public void subscribe(final String topic, final String subExpression) throws MQClientException; /** - * ȡģӵǰעϢᱻ߶ + * 取消订阅,从当前订阅组内注销,消息会被订阅组内其他订阅者订阅 * * @param topic - * Ϣ + * 消息主题 */ public void unsubscribe(final String topic); /** - * ̹߳ͣ + * 动态调整消费线程池线程数量 + * + * @param corePoolSize + */ + public void updateCorePoolSize(int corePoolSize); + + + /** + * 消费线程挂起,暂停消费 */ public void suspend(); /** - * ָ̻߳ + * 消费线程恢复,继续消费 */ public void resume(); } diff --git a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/consumer/MessageQueueListener.java b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/consumer/MessageQueueListener.java index a0e52e39..9d0c8db9 100644 --- a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/consumer/MessageQueueListener.java +++ b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/consumer/MessageQueueListener.java @@ -1,18 +1,32 @@ /** - * $Id: MessageQueueListener.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.client.consumer; -import java.util.List; +import java.util.Set; -import com.alibaba.rocketmq.common.MessageQueue; +import com.alibaba.rocketmq.common.message.MessageQueue; /** - * б仯 + * 队列变化监听器 * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * @author shijia.wxr + * @since 2013-7-24 */ public interface MessageQueueListener { - public void messageQueueChanged(final String topic, final List mqAll, final List mqDivided); + public void messageQueueChanged(final String topic, final Set mqAll, + final Set mqDivided); } diff --git a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/consumer/PullCallback.java b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/consumer/PullCallback.java index e9f19229..cde8811e 100644 --- a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/consumer/PullCallback.java +++ b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/consumer/PullCallback.java @@ -1,13 +1,25 @@ /** - * $Id: PullCallback.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.client.consumer; /** - * 첽Ϣصӿ - * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * 异步拉消息回调接口 * + * @author shijia.wxr + * @since 2013-7-24 */ public interface PullCallback { public void onSuccess(final PullResult pullResult); diff --git a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/consumer/PullResult.java b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/consumer/PullResult.java index 0d91c909..fe04077d 100644 --- a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/consumer/PullResult.java +++ b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/consumer/PullResult.java @@ -1,17 +1,30 @@ /** - * $Id: PullResult.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.client.consumer; import java.util.List; -import com.alibaba.rocketmq.common.MessageExt; +import com.alibaba.rocketmq.common.message.MessageExt; /** - * Ϣؽ + * 拉消息返回结果 * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * @author shijia.wxr + * @since 2013-7-24 */ public class PullResult { private final PullStatus pullStatus; @@ -64,7 +77,8 @@ public void setMsgFoundList(List msgFoundList) { @Override public String toString() { - return "PullResult [pullStatus=" + pullStatus + ", nextBeginOffset=" + nextBeginOffset + ", minOffset=" - + minOffset + ", maxOffset=" + maxOffset + ", msgFoundList=" + msgFoundList.size() + "]"; + return "PullResult [pullStatus=" + pullStatus + ", nextBeginOffset=" + nextBeginOffset + + ", minOffset=" + minOffset + ", maxOffset=" + maxOffset + ", msgFoundList=" + + (msgFoundList == null ? 0 : msgFoundList.size()) + "]"; } } diff --git a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/consumer/PullStatus.java b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/consumer/PullStatus.java index dfea2bb8..e4e9b358 100644 --- a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/consumer/PullStatus.java +++ b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/consumer/PullStatus.java @@ -1,27 +1,39 @@ /** - * $Id: PullStatus.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.client.consumer; /** - * @author vintage.wang@gmail.com shijia.wxr@taobao.com - * + * @author shijia.wxr + * @since 2013-7-24 */ public enum PullStatus { /** - * ҵϢ + * 找到消息 */ FOUND, /** - * ûµϢԱȡ + * 没有新的消息可以被拉取 */ NO_NEW_MSG, /** - * ˺ûƥϢ + * 经过过滤后,没有匹配的消息 */ NO_MATCHED_MSG, /** - * OffsetϷܹ߹С + * Offset不合法,可能过大或者过小 */ OFFSET_ILLEGAL } diff --git a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/consumer/listener/ConsumeConcurrentlyContext.java b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/consumer/listener/ConsumeConcurrentlyContext.java index d04eddce..134a7022 100644 --- a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/consumer/listener/ConsumeConcurrentlyContext.java +++ b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/consumer/listener/ConsumeConcurrentlyContext.java @@ -1,25 +1,45 @@ /** - * $Id: ConsumeConcurrentlyContext.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.client.consumer.listener; -import com.alibaba.rocketmq.common.MessageQueue; +import com.alibaba.rocketmq.common.message.MessageQueue; /** - * ϢģͬһеϢᲢѣϢ˳ + * 消费消息上下文,同一队列的消息会并行消费,消息无顺序性 * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * @author shijia.wxr + * @since 2013-7-24 */ public class ConsumeConcurrentlyContext { /** - * ҪѵϢĸ + * 要消费的消息属于哪个队列 */ private final MessageQueue messageQueue; /** - * 0ʾɿͻ˾ + * 下次消息重试延时时间
+ * -1,表示不重试,直接进入死信队列
+ * 0,表示由服务器根据重试次数自动叠加
+ * >0,表示客户端强制指定延时Level */ private int delayLevelWhenNextConsume = 0; + /** + * 对于批量消费,ack至哪条消息,默认全部ack,至最后一条消息 + */ + private int ackIndex = Integer.MAX_VALUE; public ConsumeConcurrentlyContext(MessageQueue messageQueue) { @@ -40,4 +60,14 @@ public void setDelayLevelWhenNextConsume(int delayLevelWhenNextConsume) { public MessageQueue getMessageQueue() { return messageQueue; } + + + public int getAckIndex() { + return ackIndex; + } + + + public void setAckIndex(int ackIndex) { + this.ackIndex = ackIndex; + } } diff --git a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/consumer/listener/ConsumeConcurrentlyStatus.java b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/consumer/listener/ConsumeConcurrentlyStatus.java index de0528fe..eb73ac85 100644 --- a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/consumer/listener/ConsumeConcurrentlyStatus.java +++ b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/consumer/listener/ConsumeConcurrentlyStatus.java @@ -1,13 +1,29 @@ /** - * $Id: ConsumeConcurrentlyStatus.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.client.consumer.listener; /** - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * 并行消费,消费结果 * + * @author shijia.wxr + * @since 2013-7-24 */ public enum ConsumeConcurrentlyStatus { + // 表示消费成功 CONSUME_SUCCESS, + // 表示消费失败,但是稍后还会重新消费这批消息 RECONSUME_LATER, } diff --git a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/consumer/listener/ConsumeOrderlyContext.java b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/consumer/listener/ConsumeOrderlyContext.java index 9eb1b6da..e5de9722 100644 --- a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/consumer/listener/ConsumeOrderlyContext.java +++ b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/consumer/listener/ConsumeOrderlyContext.java @@ -1,27 +1,40 @@ /** - * $Id: ConsumeOrderlyContext.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.client.consumer.listener; -import com.alibaba.rocketmq.common.MessageQueue; +import com.alibaba.rocketmq.common.message.MessageQueue; /** - * ϢģͬһеϢͬһʱֻһ߳ѣɱ֤ͬһϢ˳ + * 消费消息上下文,同一队列的消息同一时刻只有一个线程消费,可保证同一队列消息顺序消费 * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * @author shijia.wxr + * @since 2013-7-24 */ public class ConsumeOrderlyContext { /** - * ҪѵϢĸ + * 要消费的消息属于哪个队列 */ private final MessageQueue messageQueue; /** - * ϢOffsetǷԶύ + * 消息Offset是否自动提交 */ private boolean autoCommit = true; /** - * ǰйʱ䣬λ + * 将当前队列挂起时间,单位毫秒 */ private long suspendCurrentQueueTimeMillis = 1000; diff --git a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/consumer/listener/ConsumeOrderlyStatus.java b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/consumer/listener/ConsumeOrderlyStatus.java index 2aca0896..7cac5e64 100644 --- a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/consumer/listener/ConsumeOrderlyStatus.java +++ b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/consumer/listener/ConsumeOrderlyStatus.java @@ -1,22 +1,33 @@ /** - * $Id: ConsumeOrderlyStatus.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.client.consumer.listener; /** + * 顺序消费,消费结果 * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com - * + * @author shijia.wxr + * @since 2013-7-24 */ public enum ConsumeOrderlyStatus { - // Ϣɹ + // 消息处理成功 SUCCESS, - // عϢ + // 回滚消息 ROLLBACK, - // ύϢ + // 提交消息 COMMIT, - // - RETRY_IMMEDIATELY, - // ǰйһС + // 将当前队列挂起一小会儿 SUSPEND_CURRENT_QUEUE_A_MOMENT, } diff --git a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/consumer/listener/MessageListener.java b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/consumer/listener/MessageListener.java index ec8a1ca8..00ca70d5 100644 --- a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/consumer/listener/MessageListener.java +++ b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/consumer/listener/MessageListener.java @@ -1,14 +1,26 @@ /** - * $Id: MessageListener.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.client.consumer.listener; - - /** - * ϢʽϢʹãҪûʵ + * 消息监听器,被动方式订阅消息使用,需要用户实现
+ * 应用不可以直接继承此接口 * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * @author shijia.wxr + * @since 2013-7-24 */ public interface MessageListener { } diff --git a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/consumer/listener/MessageListenerConcurrently.java b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/consumer/listener/MessageListenerConcurrently.java index f291a65d..59b8d9d4 100644 --- a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/consumer/listener/MessageListenerConcurrently.java +++ b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/consumer/listener/MessageListenerConcurrently.java @@ -1,24 +1,39 @@ /** - * $Id: MessageListenerConcurrently.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.client.consumer.listener; import java.util.List; -import com.alibaba.rocketmq.common.MessageExt; +import com.alibaba.rocketmq.common.message.MessageExt; /** - * ͬһеϢ - * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * 同一队列的消息并行消费 * + * @author shijia.wxr + * @since 2013-7-24 */ public interface MessageListenerConcurrently extends MessageListener { /** - * ׳쳣ͬڷ ConsumeConcurrentlyStatus.RECONSUME_LATER + * 方法抛出异常等同于返回 ConsumeConcurrentlyStatus.RECONSUME_LATER
+ * P.S: 建议应用不要抛出异常 * * @param msgs + * msgs.size() >= 1
+ * DefaultMQPushConsumer.consumeMessageBatchMaxSize=1,默认消息数为1 * @param context * @return */ diff --git a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/consumer/listener/MessageListenerOrderly.java b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/consumer/listener/MessageListenerOrderly.java index 78acb59e..0d953608 100644 --- a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/consumer/listener/MessageListenerOrderly.java +++ b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/consumer/listener/MessageListenerOrderly.java @@ -1,27 +1,42 @@ /** - * $Id: MessageListenerOrderly.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.client.consumer.listener; import java.util.List; -import com.alibaba.rocketmq.common.MessageExt; +import com.alibaba.rocketmq.common.message.MessageExt; /** - * ͬһеϢͬһʱֻһ߳ѣɱ֤Ϣͬһϸ - * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * 同一队列的消息同一时刻只能一个线程消费,可保证消息在同一队列严格有序消费 * + * @author shijia.wxr + * @since 2013-7-24 */ public interface MessageListenerOrderly extends MessageListener { /** - * ׳쳣ͬڷ ConsumeOrderlyStatus.SUSPEND_CURRENT_QUEUE_A_MOMENT + * 方法抛出异常等同于返回 ConsumeOrderlyStatus.SUSPEND_CURRENT_QUEUE_A_MOMENT
+ * P.S: 建议应用不要抛出异常 * * @param msgs - * msgs.size() >= 1 + * msgs.size() >= 1
+ * DefaultMQPushConsumer.consumeMessageBatchMaxSize=1,默认消息数为1 * @param context * @return */ - public ConsumeOrderlyStatus consumeMessage(final List msgs, final ConsumeOrderlyContext context); + public ConsumeOrderlyStatus consumeMessage(final List msgs, + final ConsumeOrderlyContext context); } diff --git a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/consumer/loadbalance/AllocateMessageQueueAveragely.java b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/consumer/loadbalance/AllocateMessageQueueAveragely.java deleted file mode 100644 index 7eeb789f..00000000 --- a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/consumer/loadbalance/AllocateMessageQueueAveragely.java +++ /dev/null @@ -1,41 +0,0 @@ -/** - * $Id: AllocateMessageQueueAveragely.java 1831 2013-05-16 01:39:51Z shijia.wxr $ - */ -package com.alibaba.rocketmq.client.consumer.loadbalance; - -import java.util.ArrayList; -import java.util.List; - -import com.alibaba.rocketmq.client.consumer.AllocateMessageQueueStrategy; -import com.alibaba.rocketmq.common.MessageQueue; - - -/** - * ƽ㷨 - * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com - * - */ -public class AllocateMessageQueueAveragely implements AllocateMessageQueueStrategy { - @Override - public List allocate(String group, String topic, String currentCID, List mqAll, - List cidAll) { - List result = new ArrayList(); - int currentIndex = cidAll.indexOf(currentCID); - if (currentIndex < 0) { - return result; - } - - int mod = mqAll.size() / cidAll.size(); - int rem = mqAll.size() % cidAll.size(); - int startindex = mod * currentIndex; - int endindex = startindex + mod; - for (int i = startindex; i < endindex; i++) { - result.add(mqAll.get(i)); - } - if (rem > currentIndex) { - result.add(mqAll.get(currentIndex + mod * cidAll.size())); - } - return result; - } -} diff --git a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/consumer/loadbalance/AllocateMessageQueueByConfig.java b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/consumer/loadbalance/AllocateMessageQueueByConfig.java deleted file mode 100644 index 3a8d3daf..00000000 --- a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/consumer/loadbalance/AllocateMessageQueueByConfig.java +++ /dev/null @@ -1,37 +0,0 @@ -/** - * $Id: AllocateMessageQueueByConfig.java 1831 2013-05-16 01:39:51Z shijia.wxr $ - */ -package com.alibaba.rocketmq.client.consumer.loadbalance; - -import java.util.List; - -import com.alibaba.rocketmq.client.consumer.AllocateMessageQueueStrategy; -import com.alibaba.rocketmq.common.MessageQueue; - - -/** - * УӦʹSpringʼ - * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com - * - */ -public class AllocateMessageQueueByConfig implements AllocateMessageQueueStrategy { - private List messageQueueList; - - - @Override - public List allocate(String group, String topic, String currentCID, List mqAll, - List cidAll) { - return this.messageQueueList; - } - - - public List getMessageQueueList() { - return messageQueueList; - } - - - public void setMessageQueueList(List messageQueueList) { - this.messageQueueList = messageQueueList; - } -} diff --git a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/consumer/loadbalance/AllocateMessageQueueByMachineRoom.java b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/consumer/loadbalance/AllocateMessageQueueByMachineRoom.java deleted file mode 100644 index a5fcbde1..00000000 --- a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/consumer/loadbalance/AllocateMessageQueueByMachineRoom.java +++ /dev/null @@ -1,26 +0,0 @@ -/** - * $Id: AllocateMessageQueueByMachineRoom.java 1831 2013-05-16 01:39:51Z shijia.wxr $ - */ -package com.alibaba.rocketmq.client.consumer.loadbalance; - -import java.util.List; - -import com.alibaba.rocketmq.client.consumer.AllocateMessageQueueStrategy; -import com.alibaba.rocketmq.common.MessageQueue; - - -/** - * ջУ֧߼ - * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com - * - */ -public class AllocateMessageQueueByMachineRoom implements AllocateMessageQueueStrategy { - - @Override - public List allocate(String group, String topic, String currentCID, List mqAll, - List cidAll) { - // TODO Auto-generated method stub - return mqAll; - } -} diff --git a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/consumer/rebalance/AllocateMessageQueueAveragely.java b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/consumer/rebalance/AllocateMessageQueueAveragely.java new file mode 100644 index 00000000..267c3a68 --- /dev/null +++ b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/consumer/rebalance/AllocateMessageQueueAveragely.java @@ -0,0 +1,62 @@ +/** + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.rocketmq.client.consumer.rebalance; + +import java.util.ArrayList; +import java.util.List; + +import com.alibaba.rocketmq.client.consumer.AllocateMessageQueueStrategy; +import com.alibaba.rocketmq.common.message.MessageQueue; + + +/** + * 平均分配队列算法 + * + * @author fuchong + * @author manhong.yqd + * @since 2013-7-24 + */ +public class AllocateMessageQueueAveragely implements AllocateMessageQueueStrategy { + @Override + public List allocate(String currentCID, List mqAll, List cidAll) { + if (currentCID == null || currentCID.length() < 1) { + throw new IllegalArgumentException("currentCID is empty"); + } + if (mqAll == null || mqAll.size() < 1) { + throw new IllegalArgumentException("mqAll is null or mqAll size < 1"); + } + if (cidAll == null || cidAll.size() < 1) { + throw new IllegalArgumentException("cidAll is null or cidAll size < 1"); + } + + List result = new ArrayList(); + if (!cidAll.contains(currentCID)) { // 不存在此ConsumerId ,直接返回 + return result; + } + + int index = cidAll.indexOf(currentCID); + int mod = mqAll.size() % cidAll.size(); + int averageSize = + mqAll.size() <= cidAll.size() ? 1 : (mod > 0 && index < mod ? mqAll.size() / cidAll.size() + + 1 : mqAll.size() / cidAll.size()); + int startIndex = (mod > 0 && index < mod) ? index * averageSize : index * averageSize + mod; + int range = Math.min(averageSize, mqAll.size() - startIndex); + for (int i = 0; i < range; i++) { + result.add(mqAll.get((startIndex + i) % mqAll.size())); + } + return result; + } +} diff --git a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/consumer/rebalance/AllocateMessageQueueByConfig.java b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/consumer/rebalance/AllocateMessageQueueByConfig.java new file mode 100644 index 00000000..a40e5992 --- /dev/null +++ b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/consumer/rebalance/AllocateMessageQueueByConfig.java @@ -0,0 +1,48 @@ +/** + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.rocketmq.client.consumer.rebalance; + +import java.util.List; + +import com.alibaba.rocketmq.client.consumer.AllocateMessageQueueStrategy; +import com.alibaba.rocketmq.common.message.MessageQueue; + + +/** + * 按照配置来分配队列,建议应用使用Spring来初始化 + * + * @author shijia.wxr + * @since 2013-7-24 + */ +public class AllocateMessageQueueByConfig implements AllocateMessageQueueStrategy { + private List messageQueueList; + + + @Override + public List allocate(String currentCID, List mqAll, List cidAll) { + return this.messageQueueList; + } + + + public List getMessageQueueList() { + return messageQueueList; + } + + + public void setMessageQueueList(List messageQueueList) { + this.messageQueueList = messageQueueList; + } +} diff --git a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/consumer/rebalance/AllocateMessageQueueByMachineRoom.java b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/consumer/rebalance/AllocateMessageQueueByMachineRoom.java new file mode 100644 index 00000000..b46958fa --- /dev/null +++ b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/consumer/rebalance/AllocateMessageQueueByMachineRoom.java @@ -0,0 +1,73 @@ +/** + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.rocketmq.client.consumer.rebalance; + +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +import com.alibaba.rocketmq.client.consumer.AllocateMessageQueueStrategy; +import com.alibaba.rocketmq.common.message.MessageQueue; + + +/** + * 按照机房来分配队列,例如支付宝逻辑机房 + * + * @author linye + * @since 2013-7-24 + */ +public class AllocateMessageQueueByMachineRoom implements AllocateMessageQueueStrategy { + private Set consumeridcs; + + + @Override + public List allocate(String currentCID, List mqAll, List cidAll) { + List result = new ArrayList(); + int currentIndex = cidAll.indexOf(currentCID); + if (currentIndex < 0) { + return result; + } + List premqAll = new ArrayList(); + for (MessageQueue mq : mqAll) { + String[] temp = mq.getBrokerName().split("@"); + if (temp.length == 2 && consumeridcs.contains(temp[0])) { + premqAll.add(mq); + } + } + // Todo cid + int mod = premqAll.size() / cidAll.size(); + int rem = premqAll.size() % cidAll.size(); + int startindex = mod * currentIndex; + int endindex = startindex + mod; + for (int i = startindex; i < endindex; i++) { + result.add(mqAll.get(i)); + } + if (rem > currentIndex) { + result.add(premqAll.get(currentIndex + mod * cidAll.size())); + } + return result; + } + + + public Set getConsumeridcs() { + return consumeridcs; + } + + + public void setConsumeridcs(Set consumeridcs) { + this.consumeridcs = consumeridcs; + } +} diff --git a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/consumer/store/LocalFileOffsetStore.java b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/consumer/store/LocalFileOffsetStore.java new file mode 100644 index 00000000..438da0ec --- /dev/null +++ b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/consumer/store/LocalFileOffsetStore.java @@ -0,0 +1,213 @@ +/** + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.rocketmq.client.consumer.store; + +import java.io.File; +import java.io.IOException; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicLong; + +import org.slf4j.Logger; + +import com.alibaba.rocketmq.client.exception.MQClientException; +import com.alibaba.rocketmq.client.impl.factory.MQClientFactory; +import com.alibaba.rocketmq.client.log.ClientLogger; +import com.alibaba.rocketmq.common.MixAll; +import com.alibaba.rocketmq.common.UtilAll; +import com.alibaba.rocketmq.common.help.FAQUrl; +import com.alibaba.rocketmq.common.message.MessageQueue; + + +/** + * 消费进度存储到Consumer本地 + * + * @author shijia.wxr + * @since 2013-7-24 + */ +public class LocalFileOffsetStore implements OffsetStore { + public final static String LocalOffsetStoreDir = System.getProperty( + "rocketmq.client.localOffsetStoreDir", // + System.getProperty("user.home") + File.separator + ".rocketmq_offsets"); + private final static Logger log = ClientLogger.getLog(); + private final MQClientFactory mQClientFactory; + private final String groupName; + // 本地Offset存储路径 + private final String storePath; + private ConcurrentHashMap offsetTable = + new ConcurrentHashMap(); + + + public LocalFileOffsetStore(MQClientFactory mQClientFactory, String groupName) { + this.mQClientFactory = mQClientFactory; + this.groupName = groupName; + this.storePath = LocalOffsetStoreDir + File.separator + // + this.mQClientFactory.getClientId() + File.separator + // + this.groupName + File.separator + // + "offsets.json"; + } + + + @Override + public void load() throws MQClientException { + OffsetSerializeWrapper offsetSerializeWrapper = this.readLocalOffset(); + if (offsetSerializeWrapper != null && offsetSerializeWrapper.getOffsetTable() != null) { + offsetTable.putAll(offsetSerializeWrapper.getOffsetTable()); + + for (MessageQueue mq : offsetSerializeWrapper.getOffsetTable().keySet()) { + AtomicLong offset = offsetSerializeWrapper.getOffsetTable().get(mq); + log.info("load consumer's offset, {} {} {}",// + this.groupName,// + mq,// + offset.get()); + } + } + } + + + @Override + public void updateOffset(MessageQueue mq, long offset, boolean increaseOnly) { + if (mq != null) { + AtomicLong offsetOld = this.offsetTable.get(mq); + if (null == offsetOld) { + offsetOld = this.offsetTable.putIfAbsent(mq, new AtomicLong(offset)); + } + + if (null != offsetOld) { + if (increaseOnly) { + MixAll.compareAndIncreaseOnly(offsetOld, offset); + } + else { + offsetOld.set(offset); + } + } + } + } + + + @Override + public long readOffset(final MessageQueue mq, final ReadOffsetType type) { + if (mq != null) { + switch (type) { + case MEMORY_FIRST_THEN_STORE: + case READ_FROM_MEMORY: { + AtomicLong offset = this.offsetTable.get(mq); + if (offset != null) { + return offset.get(); + } + else if (ReadOffsetType.READ_FROM_MEMORY == type) { + return -1; + } + } + case READ_FROM_STORE: { + OffsetSerializeWrapper offsetSerializeWrapper; + try { + offsetSerializeWrapper = this.readLocalOffset(); + } + catch (MQClientException e) { + return -1; + } + if (offsetSerializeWrapper != null && offsetSerializeWrapper.getOffsetTable() != null) { + AtomicLong offset = offsetSerializeWrapper.getOffsetTable().get(mq); + if (offset != null) { + this.updateOffset(mq, offset.get(), false); + return offset.get(); + } + } + } + default: + break; + } + } + + return -1; + } + + + @Override + public void persistAll(Set mqs) { + if (null == mqs || mqs.isEmpty()) + return; + + OffsetSerializeWrapper offsetSerializeWrapper = new OffsetSerializeWrapper(); + for (MessageQueue mq : this.offsetTable.keySet()) { + if (mqs.contains(mq)) { + AtomicLong offset = this.offsetTable.get(mq); + offsetSerializeWrapper.getOffsetTable().put(mq, offset); + } + } + + String jsonString = offsetSerializeWrapper.toJson(true); + if (jsonString != null) { + try { + MixAll.string2File(jsonString, this.storePath); + } + catch (IOException e) { + log.error("persistAll consumer offset Exception, " + this.storePath, e); + } + } + } + + + @Override + public void persist(MessageQueue mq) { + } + + + private OffsetSerializeWrapper readLocalOffset() throws MQClientException { + String content = MixAll.file2String(this.storePath); + if (content != null) { + OffsetSerializeWrapper offsetSerializeWrapper; + try { + offsetSerializeWrapper = + OffsetSerializeWrapper.fromJson(content, OffsetSerializeWrapper.class); + } + catch (Exception e) { + log.warn("readLocalOffset Exception", e); + throw new MQClientException("readLocalOffset Exception, maybe fastjson version too low" // + + FAQUrl.suggestTodo(FAQUrl.LOAD_JSON_EXCEPTION), // + e); + } + return offsetSerializeWrapper; + } + + return null; + } + + + @Override + public void removeOffset(MessageQueue mq) { + // 消费进度存储到Consumer本地时暂不做 offset 清理 + } + + + @Override + public Map cloneOffsetTable(String topic) { + Map cloneOffsetTable = new HashMap(); + Iterator iterator = this.offsetTable.keySet().iterator(); + while (iterator.hasNext()) { + MessageQueue mq = iterator.next(); + if (!UtilAll.isBlank(topic) && !topic.equals(mq.getTopic())) { + continue; + } + cloneOffsetTable.put(mq, this.offsetTable.get(mq).get()); + } + return cloneOffsetTable; + } +} diff --git a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/consumer/store/OffsetSerializeWrapper.java b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/consumer/store/OffsetSerializeWrapper.java new file mode 100644 index 00000000..7d1d95ee --- /dev/null +++ b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/consumer/store/OffsetSerializeWrapper.java @@ -0,0 +1,44 @@ +/** + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.rocketmq.client.consumer.store; + +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicLong; + +import com.alibaba.rocketmq.common.message.MessageQueue; +import com.alibaba.rocketmq.remoting.protocol.RemotingSerializable; + + +/** + * Offset持久化,json包装类 + * + * @author shijia.wxr + * @since 2013-7-25 + */ +public class OffsetSerializeWrapper extends RemotingSerializable { + private ConcurrentHashMap offsetTable = + new ConcurrentHashMap(); + + + public ConcurrentHashMap getOffsetTable() { + return offsetTable; + } + + + public void setOffsetTable(ConcurrentHashMap offsetTable) { + this.offsetTable = offsetTable; + } +} diff --git a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/consumer/store/OffsetStore.java b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/consumer/store/OffsetStore.java new file mode 100644 index 00000000..58748b80 --- /dev/null +++ b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/consumer/store/OffsetStore.java @@ -0,0 +1,71 @@ +/** + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.rocketmq.client.consumer.store; + +import java.util.Map; +import java.util.Set; + +import com.alibaba.rocketmq.client.exception.MQClientException; +import com.alibaba.rocketmq.common.message.MessageQueue; + + +/** + * Consumer Offset存储接口 + * + * @author shijia.wxr + * @since 2013-7-25 + */ +public interface OffsetStore { + /** + * 加载Offset + * + * @throws MQClientException + */ + public void load() throws MQClientException; + + + /** + * 更新消费进度,存储到内存 + */ + public void updateOffset(final MessageQueue mq, final long offset, final boolean increaseOnly); + + + /** + * 从本地缓存读取消费进度 + */ + public long readOffset(final MessageQueue mq, final ReadOffsetType type); + + + /** + * 持久化全部消费进度,可能持久化本地或者远端Broker + */ + public void persistAll(final Set mqs); + + + public void persist(final MessageQueue mq); + + + /** + * 删除不必要的MessageQueue offset + */ + public void removeOffset(MessageQueue mq); + + + /** + * 如果 topic 为空,则不对 topic 进行过滤,全部拷贝。 + */ + public Map cloneOffsetTable(String topic); +} diff --git a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/consumer/store/ReadOffsetType.java b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/consumer/store/ReadOffsetType.java new file mode 100644 index 00000000..9a485df3 --- /dev/null +++ b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/consumer/store/ReadOffsetType.java @@ -0,0 +1,25 @@ +/** + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.rocketmq.client.consumer.store; + +public enum ReadOffsetType { + // 只从Memory读取 + READ_FROM_MEMORY, + // 只从存储层读取(本地或者远端) + READ_FROM_STORE, + // 先从内存读,内存不存在再从存储层读 + MEMORY_FIRST_THEN_STORE, +} diff --git a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/consumer/store/RemoteBrokerOffsetStore.java b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/consumer/store/RemoteBrokerOffsetStore.java new file mode 100644 index 00000000..0d38b5ad --- /dev/null +++ b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/consumer/store/RemoteBrokerOffsetStore.java @@ -0,0 +1,262 @@ +/** + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.rocketmq.client.consumer.store; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicLong; + +import org.slf4j.Logger; + +import com.alibaba.rocketmq.client.exception.MQBrokerException; +import com.alibaba.rocketmq.client.exception.MQClientException; +import com.alibaba.rocketmq.client.impl.FindBrokerResult; +import com.alibaba.rocketmq.client.impl.factory.MQClientFactory; +import com.alibaba.rocketmq.client.log.ClientLogger; +import com.alibaba.rocketmq.common.MixAll; +import com.alibaba.rocketmq.common.UtilAll; +import com.alibaba.rocketmq.common.message.MessageQueue; +import com.alibaba.rocketmq.common.protocol.header.QueryConsumerOffsetRequestHeader; +import com.alibaba.rocketmq.common.protocol.header.UpdateConsumerOffsetRequestHeader; +import com.alibaba.rocketmq.remoting.exception.RemotingException; + + +/** + * 消费进度存储到远端Broker,比较可靠 + * + * @author shijia.wxr + * @since 2013-7-24 + */ +public class RemoteBrokerOffsetStore implements OffsetStore { + private final static Logger log = ClientLogger.getLog(); + private final MQClientFactory mQClientFactory; + private final String groupName; + private final AtomicLong storeTimesTotal = new AtomicLong(0); + private ConcurrentHashMap offsetTable = + new ConcurrentHashMap(); + + + public RemoteBrokerOffsetStore(MQClientFactory mQClientFactory, String groupName) { + this.mQClientFactory = mQClientFactory; + this.groupName = groupName; + } + + + @Override + public void load() { + } + + + @Override + public void updateOffset(MessageQueue mq, long offset, boolean increaseOnly) { + if (mq != null) { + AtomicLong offsetOld = this.offsetTable.get(mq); + if (null == offsetOld) { + offsetOld = this.offsetTable.putIfAbsent(mq, new AtomicLong(offset)); + } + + if (null != offsetOld) { + if (increaseOnly) { + MixAll.compareAndIncreaseOnly(offsetOld, offset); + } + else { + offsetOld.set(offset); + } + } + } + } + + + @Override + public long readOffset(final MessageQueue mq, final ReadOffsetType type) { + if (mq != null) { + switch (type) { + case MEMORY_FIRST_THEN_STORE: + case READ_FROM_MEMORY: { + AtomicLong offset = this.offsetTable.get(mq); + if (offset != null) { + return offset.get(); + } + else if (ReadOffsetType.READ_FROM_MEMORY == type) { + return -1; + } + } + case READ_FROM_STORE: { + try { + long brokerOffset = this.fetchConsumeOffsetFromBroker(mq); + AtomicLong offset = new AtomicLong(brokerOffset); + this.updateOffset(mq, offset.get(), false); + return brokerOffset; + } + // 当前订阅组在服务器没有对应的Offset + catch (MQBrokerException e) { + return -1; + } + // 其他通信错误 + catch (Exception e) { + log.warn("fetchConsumeOffsetFromBroker exception, " + mq, e); + return -2; + } + } + default: + break; + } + } + + return -1; + } + + + @Override + public void persistAll(Set mqs) { + if (null == mqs || mqs.isEmpty()) + return; + + final HashSet unusedMQ = new HashSet(); + long times = this.storeTimesTotal.getAndIncrement(); + + if (mqs != null && !mqs.isEmpty()) { + for (MessageQueue mq : this.offsetTable.keySet()) { + AtomicLong offset = this.offsetTable.get(mq); + if (offset != null) { + if (mqs.contains(mq)) { + try { + this.updateConsumeOffsetToBroker(mq, offset.get()); + // 每隔1分钟打印一次消费进度 + if ((times % 12) == 0) { + log.info("Group: {} ClientId: {} updateConsumeOffsetToBroker {} {}", // + this.groupName,// + this.mQClientFactory.getClientId(),// + mq, // + offset.get()); + } + } + catch (Exception e) { + log.error("updateConsumeOffsetToBroker exception, " + mq.toString(), e); + } + } + // 本地多余的队列,需要删除掉 + else { + unusedMQ.add(mq); + } + } + } + } + + if (!unusedMQ.isEmpty()) { + for (MessageQueue mq : unusedMQ) { + this.offsetTable.remove(mq); + log.info("remove unused mq, {}, {}", mq, this.groupName); + } + } + } + + + @Override + public void persist(MessageQueue mq) { + AtomicLong offset = this.offsetTable.get(mq); + if (offset != null) { + try { + this.updateConsumeOffsetToBroker(mq, offset.get()); + log.debug("updateConsumeOffsetToBroker {} {}", mq, offset.get()); + } + catch (Exception e) { + log.error("updateConsumeOffsetToBroker exception, " + mq.toString(), e); + } + } + } + + + /** + * 更新Consumer Offset,在Master断网期间,可能会更新到Slave,这里需要优化,或者在Slave端优化, TODO + */ + private void updateConsumeOffsetToBroker(MessageQueue mq, long offset) throws RemotingException, + MQBrokerException, InterruptedException, MQClientException { + FindBrokerResult findBrokerResult = this.mQClientFactory.findBrokerAddressInAdmin(mq.getBrokerName()); + if (null == findBrokerResult) { + // TODO 此处可能对Name Server压力过大,需要调优 + this.mQClientFactory.updateTopicRouteInfoFromNameServer(mq.getTopic()); + findBrokerResult = this.mQClientFactory.findBrokerAddressInAdmin(mq.getBrokerName()); + } + + if (findBrokerResult != null) { + UpdateConsumerOffsetRequestHeader requestHeader = new UpdateConsumerOffsetRequestHeader(); + requestHeader.setTopic(mq.getTopic()); + requestHeader.setConsumerGroup(this.groupName); + requestHeader.setQueueId(mq.getQueueId()); + requestHeader.setCommitOffset(offset); + + // 使用oneway形式,原因是服务器在删除文件时,这个调用可能会超时 + this.mQClientFactory.getMQClientAPIImpl().updateConsumerOffsetOneway( + findBrokerResult.getBrokerAddr(), requestHeader, 1000 * 5); + } + else { + throw new MQClientException("The broker[" + mq.getBrokerName() + "] not exist", null); + } + } + + + private long fetchConsumeOffsetFromBroker(MessageQueue mq) throws RemotingException, MQBrokerException, + InterruptedException, MQClientException { + FindBrokerResult findBrokerResult = this.mQClientFactory.findBrokerAddressInAdmin(mq.getBrokerName()); + if (null == findBrokerResult) { + // TODO 此处可能对Name Server压力过大,需要调优 + this.mQClientFactory.updateTopicRouteInfoFromNameServer(mq.getTopic()); + findBrokerResult = this.mQClientFactory.findBrokerAddressInAdmin(mq.getBrokerName()); + } + + if (findBrokerResult != null) { + QueryConsumerOffsetRequestHeader requestHeader = new QueryConsumerOffsetRequestHeader(); + requestHeader.setTopic(mq.getTopic()); + requestHeader.setConsumerGroup(this.groupName); + requestHeader.setQueueId(mq.getQueueId()); + + return this.mQClientFactory.getMQClientAPIImpl().queryConsumerOffset( + findBrokerResult.getBrokerAddr(), requestHeader, 1000 * 5); + } + else { + throw new MQClientException("The broker[" + mq.getBrokerName() + "] not exist", null); + } + } + + + public void removeOffset(MessageQueue mq) { + if (mq != null) { + this.offsetTable.remove(mq); + log.info("remove unnecessary messageQueue offset. mq={}, offsetTableSize={}", mq, + offsetTable.size()); + } + } + + + @Override + public Map cloneOffsetTable(String topic) { + Map cloneOffsetTable = new HashMap(); + Iterator iterator = this.offsetTable.keySet().iterator(); + while (iterator.hasNext()) { + MessageQueue mq = iterator.next(); + if (!UtilAll.isBlank(topic) && !topic.equals(mq.getTopic())) { + continue; + } + cloneOffsetTable.put(mq, this.offsetTable.get(mq).get()); + } + return cloneOffsetTable; + } +} diff --git a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/exception/MQBrokerException.java b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/exception/MQBrokerException.java index 2d2858ac..171c983c 100644 --- a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/exception/MQBrokerException.java +++ b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/exception/MQBrokerException.java @@ -1,13 +1,29 @@ /** - * $Id: MQBrokerException.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.client.exception; -import com.alibaba.rocketmq.common.UtilALl; +import com.alibaba.rocketmq.common.UtilAll; +import com.alibaba.rocketmq.common.help.FAQUrl; /** - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * Broker异常 + * + * @author shijia.wxr + * @since 2013-7-24 */ public class MQBrokerException extends Exception { private static final long serialVersionUID = 5975020272601250368L; @@ -16,7 +32,8 @@ public class MQBrokerException extends Exception { public MQBrokerException(int responseCode, String errorMessage) { - super("CODE: " + UtilALl.responseCode2String(responseCode) + "\tDESC: " + errorMessage); + super(FAQUrl.attachDefaultURL("CODE: " + UtilAll.responseCode2String(responseCode) + " DESC: " + + errorMessage)); this.responseCode = responseCode; this.errorMessage = errorMessage; } @@ -30,10 +47,4 @@ public int getResponseCode() { public String getErrorMessage() { return errorMessage; } - - // - // public boolean needRetry() { - // // TODO - // return false; - // } } diff --git a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/exception/MQClientException.java b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/exception/MQClientException.java index 60b53271..20259f64 100644 --- a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/exception/MQClientException.java +++ b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/exception/MQClientException.java @@ -1,15 +1,28 @@ /** - * $Id: MQClientException.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.client.exception; -import com.alibaba.rocketmq.common.UtilALl; +import com.alibaba.rocketmq.common.UtilAll; +import com.alibaba.rocketmq.common.help.FAQUrl; /** - * MQ쳣 + * MQ异常类 * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * @author shijia.wxr */ public class MQClientException extends Exception { private static final long serialVersionUID = -5758410930844185841L; @@ -18,14 +31,15 @@ public class MQClientException extends Exception { public MQClientException(String errorMessage, Throwable cause) { - super(errorMessage, cause); + super(FAQUrl.attachDefaultURL(errorMessage), cause); this.responseCode = -1; - this.errorMessage = null; + this.errorMessage = errorMessage; } public MQClientException(int responseCode, String errorMessage) { - super("CODE: " + UtilALl.responseCode2String(responseCode) + "\tDESC: " + errorMessage); + super(FAQUrl.attachDefaultURL("CODE: " + UtilAll.responseCode2String(responseCode) + " DESC: " + + errorMessage)); this.responseCode = responseCode; this.errorMessage = errorMessage; } @@ -39,10 +53,4 @@ public int getResponseCode() { public String getErrorMessage() { return errorMessage; } - - - public boolean needRetry() { - // TODO - return false; - } } diff --git a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/hook/ConsumeMessageContext.java b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/hook/ConsumeMessageContext.java new file mode 100644 index 00000000..920d78e0 --- /dev/null +++ b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/hook/ConsumeMessageContext.java @@ -0,0 +1,87 @@ +/** + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.rocketmq.client.hook; + +import java.util.List; + +import com.alibaba.rocketmq.common.message.MessageExt; +import com.alibaba.rocketmq.common.message.MessageQueue; + + +public class ConsumeMessageContext { + private String consumerGroup; + private List msgList; + private MessageQueue mq; + private boolean success; + private Object arg; + + + public String getConsumerGroup() { + return consumerGroup; + } + + + public void setConsumerGroup(String consumerGroup) { + this.consumerGroup = consumerGroup; + } + + + public List getMsgList() { + return msgList; + } + + + public void setMsgList(List msgList) { + this.msgList = msgList; + } + + + public MessageQueue getMq() { + return mq; + } + + + public void setMq(MessageQueue mq) { + this.mq = mq; + } + + + public boolean isSuccess() { + return success; + } + + + public void setSuccess(boolean success) { + this.success = success; + } + + + public Object getArg() { + return arg; + } + + + public void setArg(Object arg) { + this.arg = arg; + } + + + @Override + public String toString() { + return "ConsumeMessageContext [consumerGroup=" + consumerGroup + ", msgList=" + msgList + ", mq=" + + mq + ", success=" + success + ", arg=" + arg + "]"; + } +} diff --git a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/hook/ConsumeMessageHook.java b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/hook/ConsumeMessageHook.java new file mode 100644 index 00000000..2fc1993f --- /dev/null +++ b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/hook/ConsumeMessageHook.java @@ -0,0 +1,26 @@ +/** + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.rocketmq.client.hook; + +public interface ConsumeMessageHook { + public String hookName(); + + + public void consumeMessageBefore(final ConsumeMessageContext context); + + + public void consumeMessageAfter(final ConsumeMessageContext context); +} diff --git a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/hook/SendMessageContext.java b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/hook/SendMessageContext.java new file mode 100644 index 00000000..1c851e32 --- /dev/null +++ b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/hook/SendMessageContext.java @@ -0,0 +1,121 @@ +/** + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.rocketmq.client.hook; + +import com.alibaba.rocketmq.client.impl.CommunicationMode; +import com.alibaba.rocketmq.client.producer.SendResult; +import com.alibaba.rocketmq.common.message.Message; +import com.alibaba.rocketmq.common.message.MessageQueue; + + +public class SendMessageContext { + private String producerGroup; + private Message message; + private MessageQueue mq; + private String brokerAddr; + private CommunicationMode communicationMode; + private SendResult sendResult; + private Exception exception; + private Object arg; + + + public String getProducerGroup() { + return producerGroup; + } + + + public void setProducerGroup(String producerGroup) { + this.producerGroup = producerGroup; + } + + + public Message getMessage() { + return message; + } + + + public void setMessage(Message message) { + this.message = message; + } + + + public MessageQueue getMq() { + return mq; + } + + + public void setMq(MessageQueue mq) { + this.mq = mq; + } + + + public String getBrokerAddr() { + return brokerAddr; + } + + + public void setBrokerAddr(String brokerAddr) { + this.brokerAddr = brokerAddr; + } + + + public CommunicationMode getCommunicationMode() { + return communicationMode; + } + + + public void setCommunicationMode(CommunicationMode communicationMode) { + this.communicationMode = communicationMode; + } + + + public SendResult getSendResult() { + return sendResult; + } + + + public void setSendResult(SendResult sendResult) { + this.sendResult = sendResult; + } + + + public Exception getException() { + return exception; + } + + + public void setException(Exception exception) { + this.exception = exception; + } + + + public Object getArg() { + return arg; + } + + + public void setArg(Object arg) { + this.arg = arg; + } + + + @Override + public String toString() { + return "SendMessageContext [producerGroup=" + producerGroup + ", message=" + message + ", mq=" + mq + + ", brokerAddr=" + brokerAddr + ", communicationMode=" + communicationMode + ", sendResult=" + + sendResult + ", exception=" + exception + ", arg=" + arg + "]"; + } +} diff --git a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/hook/SendMessageHook.java b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/hook/SendMessageHook.java new file mode 100644 index 00000000..ee89baf3 --- /dev/null +++ b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/hook/SendMessageHook.java @@ -0,0 +1,26 @@ +/** + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.rocketmq.client.hook; + +public interface SendMessageHook { + public String hookName(); + + + public void sendMessageBefore(final SendMessageContext context); + + + public void sendMessageAfter(final SendMessageContext context); +} diff --git a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/impl/ClientRemotingProcessor.java b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/impl/ClientRemotingProcessor.java index 470619e5..c3720102 100644 --- a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/impl/ClientRemotingProcessor.java +++ b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/impl/ClientRemotingProcessor.java @@ -1,35 +1,61 @@ /** - * + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.client.impl; import io.netty.channel.ChannelHandlerContext; +import java.nio.ByteBuffer; +import java.util.HashMap; +import java.util.Map; + import org.slf4j.Logger; import com.alibaba.rocketmq.client.impl.factory.MQClientFactory; +import com.alibaba.rocketmq.client.impl.producer.MQProducerInner; +import com.alibaba.rocketmq.client.log.ClientLogger; +import com.alibaba.rocketmq.common.message.MessageConst; +import com.alibaba.rocketmq.common.message.MessageDecoder; +import com.alibaba.rocketmq.common.message.MessageExt; +import com.alibaba.rocketmq.common.message.MessageQueue; import com.alibaba.rocketmq.common.protocol.MQProtos.MQRequestCode; +import com.alibaba.rocketmq.common.protocol.body.GetConsumerStatusBody; +import com.alibaba.rocketmq.common.protocol.body.ResetOffsetBody; import com.alibaba.rocketmq.common.protocol.header.CheckTransactionStateRequestHeader; -import com.alibaba.rocketmq.common.protocol.header.CheckTransactionStateResponseHeader; -import com.alibaba.rocketmq.common.protocol.header.SendMessageRequestHeader; -import com.alibaba.rocketmq.common.protocol.header.SendMessageResponseHeader; +import com.alibaba.rocketmq.common.protocol.header.GetConsumerStatusRequestHeader; +import com.alibaba.rocketmq.common.protocol.header.NotifyConsumerIdsChangedRequestHeader; +import com.alibaba.rocketmq.common.protocol.header.ResetOffsetRequestHeader; +import com.alibaba.rocketmq.remoting.common.RemotingHelper; import com.alibaba.rocketmq.remoting.exception.RemotingCommandException; import com.alibaba.rocketmq.remoting.netty.NettyRequestProcessor; import com.alibaba.rocketmq.remoting.protocol.RemotingCommand; +import com.alibaba.rocketmq.remoting.protocol.RemotingProtos; /** - * ClientBrokerĻصصص + * Client接收Broker的回调操作,例如事务回调,或者其他管理类命令回调 * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * @author shijia.wxr + * @since 2013-7-24 */ public class ClientRemotingProcessor implements NettyRequestProcessor { - private final Logger log; + private final Logger log = ClientLogger.getLog(); private final MQClientFactory mqClientFactory; - public ClientRemotingProcessor(final MQClientFactory mqClientFactory, final Logger log) { - this.log = log; + public ClientRemotingProcessor(final MQClientFactory mqClientFactory) { this.mqClientFactory = mqClientFactory; } @@ -41,6 +67,12 @@ public RemotingCommand processRequest(ChannelHandlerContext ctx, RemotingCommand switch (code) { case CHECK_TRANSACTION_STATE: return this.checkTransactionState(ctx, request); + case NOTIFY_CONSUMER_IDS_CHANGED: + return this.notifyConsumerIdsChanged(ctx, request); + case RESET_CONSUMER_CLIENT_OFFSET: + return this.resetOffset(ctx, request); + case GET_CONSUMER_STATUS_FROM_CLIENT: + return this.getConsumeStatus(ctx, request); default: break; } @@ -48,18 +80,93 @@ public RemotingCommand processRequest(ChannelHandlerContext ctx, RemotingCommand } + /** + * Oneway调用,无返回值 + */ public RemotingCommand checkTransactionState(ChannelHandlerContext ctx, RemotingCommand request) throws RemotingCommandException { - final RemotingCommand response = - RemotingCommand.createResponseCommand(CheckTransactionStateResponseHeader.class); - final CheckTransactionStateResponseHeader responseHeader = - (CheckTransactionStateResponseHeader) response.getCustomHeader(); final CheckTransactionStateRequestHeader requestHeader = (CheckTransactionStateRequestHeader) request .decodeCommandCustomHeader(CheckTransactionStateRequestHeader.class); + final ByteBuffer byteBuffer = ByteBuffer.wrap(request.getBody()); + final MessageExt messageExt = MessageDecoder.decode(byteBuffer); + if (messageExt != null) { + final String group = messageExt.getProperty(MessageConst.PROPERTY_PRODUCER_GROUP); + if (group != null) { + MQProducerInner producer = this.mqClientFactory.selectProducer(group); + if (producer != null) { + final String addr = RemotingHelper.parseChannelRemoteAddr(ctx.channel()); + producer.checkTransactionState(addr, messageExt, requestHeader); + } + else { + log.debug("checkTransactionState, pick producer by group[{}] failed", group); + } + } + else { + log.warn("checkTransactionState, pick producer group failed"); + } + } + else { + log.warn("checkTransactionState, decode message failed"); + } + + return null; + } + + + /** + * Oneway调用,无返回值 + */ + public RemotingCommand notifyConsumerIdsChanged(ChannelHandlerContext ctx, RemotingCommand request) + throws RemotingCommandException { + final NotifyConsumerIdsChangedRequestHeader requestHeader = + (NotifyConsumerIdsChangedRequestHeader) request + .decodeCommandCustomHeader(NotifyConsumerIdsChangedRequestHeader.class); + log.info("receive broker's notification[{}], the consumer group: {} changed, rebalance immediately",// + RemotingHelper.parseChannelRemoteAddr(ctx.channel()),// + requestHeader.getConsumerGroup()); + this.mqClientFactory.rebalanceImmediately(); + return null; + } + + + /** + * 重置 offset, oneWay调用,无返回值。 + */ + public RemotingCommand resetOffset(ChannelHandlerContext ctx, RemotingCommand request) + throws RemotingCommandException { + final ResetOffsetRequestHeader requestHeader = + (ResetOffsetRequestHeader) request.decodeCommandCustomHeader(ResetOffsetRequestHeader.class); + log.info( + "invoke reset offset operation from broker. brokerAddr={}, topic={}, group={}, timestamp={}", + new Object[] { RemotingHelper.parseChannelRemoteAddr(ctx.channel()), requestHeader.getTopic(), + requestHeader.getGroup(), requestHeader.getTimestamp() }); + Map offsetTable = new HashMap(); + if (request.getBody() != null) { + ResetOffsetBody body = ResetOffsetBody.decode(request.getBody(), ResetOffsetBody.class); + offsetTable = body.getOffsetTable(); + } + this.mqClientFactory.resetOffset(requestHeader.getTopic(), requestHeader.getGroup(), offsetTable); + return null; + } - response.setOpaque(request.getOpaque()); + /** + * 获取 consumer 消息消费状态。 + */ + public RemotingCommand getConsumeStatus(ChannelHandlerContext ctx, RemotingCommand request) + throws RemotingCommandException { + final RemotingCommand response = RemotingCommand.createResponseCommand(null); + final GetConsumerStatusRequestHeader requestHeader = + (GetConsumerStatusRequestHeader) request + .decodeCommandCustomHeader(GetConsumerStatusRequestHeader.class); + + Map offsetTable = + this.mqClientFactory.getConsumerStatus(requestHeader.getTopic(), requestHeader.getGroup()); + GetConsumerStatusBody body = new GetConsumerStatusBody(); + body.setMessageQueueTable(offsetTable); + response.setBody(body.encode()); + response.setCode(RemotingProtos.ResponseCode.SUCCESS_VALUE); return response; } } diff --git a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/impl/CommunicationMode.java b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/impl/CommunicationMode.java index 838fe7e1..a0635041 100644 --- a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/impl/CommunicationMode.java +++ b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/impl/CommunicationMode.java @@ -1,13 +1,25 @@ /** - * $Id: CommunicationMode.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.client.impl; /** - * ͨŷʽ - * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * 通信方式 * + * @author shijia.wxr + * @since 2013-7-24 */ public enum CommunicationMode { SYNC, diff --git a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/impl/FindBrokerResult.java b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/impl/FindBrokerResult.java index 129a11f9..89ecee4e 100644 --- a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/impl/FindBrokerResult.java +++ b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/impl/FindBrokerResult.java @@ -1,11 +1,23 @@ /** - * $Id: FindBrokerResult.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.client.impl; /** - * @author vintage.wang@gmail.com shijia.wxr@taobao.com - * + * @author shijia.wxr + * @since 2013-7-24 */ public class FindBrokerResult { private final String brokerAddr; diff --git a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/impl/MQAdminImpl.java b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/impl/MQAdminImpl.java index e0cfa44b..e0fb1df0 100644 --- a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/impl/MQAdminImpl.java +++ b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/impl/MQAdminImpl.java @@ -1,5 +1,17 @@ /** - * $Id: MQAdminImpl.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.client.impl; @@ -8,22 +20,26 @@ import java.util.Collections; import java.util.LinkedList; import java.util.List; +import java.util.Set; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; +import org.slf4j.Logger; + import com.alibaba.rocketmq.client.QueryResult; import com.alibaba.rocketmq.client.exception.MQBrokerException; import com.alibaba.rocketmq.client.exception.MQClientException; import com.alibaba.rocketmq.client.impl.factory.MQClientFactory; import com.alibaba.rocketmq.client.impl.producer.TopicPublishInfo; -import com.alibaba.rocketmq.common.Message; -import com.alibaba.rocketmq.common.MessageExt; -import com.alibaba.rocketmq.common.MessageDecoder; -import com.alibaba.rocketmq.common.MessageId; +import com.alibaba.rocketmq.client.log.ClientLogger; import com.alibaba.rocketmq.common.MixAll; -import com.alibaba.rocketmq.common.MessageQueue; import com.alibaba.rocketmq.common.TopicConfig; -import com.alibaba.rocketmq.common.TopicFilterType; +import com.alibaba.rocketmq.common.help.FAQUrl; +import com.alibaba.rocketmq.common.message.MessageConst; +import com.alibaba.rocketmq.common.message.MessageDecoder; +import com.alibaba.rocketmq.common.message.MessageExt; +import com.alibaba.rocketmq.common.message.MessageId; +import com.alibaba.rocketmq.common.message.MessageQueue; import com.alibaba.rocketmq.common.protocol.header.QueryMessageRequestHeader; import com.alibaba.rocketmq.common.protocol.header.QueryMessageResponseHeader; import com.alibaba.rocketmq.common.protocol.route.BrokerData; @@ -38,12 +54,13 @@ /** - * ӿʵ - * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * 管理类接口实现 * + * @author shijia.wxr + * @since 2013-7-24 */ public class MQAdminImpl { + private final Logger log = ClientLogger.getLog(); private final MQClientFactory mQClientFactory; @@ -52,28 +69,26 @@ public MQAdminImpl(MQClientFactory mQClientFactory) { } - public void createTopic(String key, String newTopic, int queueNum, TopicFilterType topicFilterType, - boolean order) throws MQClientException { + public void createTopic(String key, String newTopic, int queueNum) throws MQClientException { try { TopicRouteData topicRouteData = this.mQClientFactory.getMQClientAPIImpl().getTopicRouteInfoFromNameServer(key, 1000 * 3); List brokerDataList = topicRouteData.getBrokerDatas(); if (brokerDataList != null && !brokerDataList.isEmpty()) { - // ԭ򣺼ʹû˳ϢģʽĬ϶е˳ͬõһ¡ + // 排序原因:即使没有配置顺序消息模式,默认队列的顺序同配置的一致。 Collections.sort(brokerDataList); MQClientException exception = null; StringBuilder orderTopicString = new StringBuilder(); - // Broker + // 遍历各个Broker for (BrokerData brokerData : brokerDataList) { String addr = brokerData.getBrokerAddrs().get(MixAll.MASTER_ID); if (addr != null) { TopicConfig topicConfig = new TopicConfig(newTopic); topicConfig.setReadQueueNums(queueNum); topicConfig.setWriteQueueNums(queueNum); - topicConfig.setTopicFilterType(topicFilterType); try { this.mQClientFactory.getMQClientAPIImpl().createTopic(addr, key, topicConfig, 1000 * 3); @@ -92,12 +107,6 @@ public void createTopic(String key, String newTopic, int queueNum, TopicFilterTy if (exception != null) { throw exception; } - - if (order) { - // Name Serverע˳Ϣ - this.mQClientFactory.getMQClientAPIImpl().registerOrderTopic(newTopic, - orderTopicString.toString(), 1000 * 10); - } } else { throw new MQClientException("Not found broker, maybe key is wrong", null); @@ -112,7 +121,8 @@ public void createTopic(String key, String newTopic, int queueNum, TopicFilterTy public List fetchPublishMessageQueues(String topic) throws MQClientException { try { TopicRouteData topicRouteData = - this.mQClientFactory.getMQClientAPIImpl().getTopicRouteInfoFromNameServer(topic, 1000 * 3); + this.mQClientFactory.getMQClientAPIImpl() + .getTopicRouteInfoFromNameServer(topic, 1000 * 3); if (topicRouteData != null) { TopicPublishInfo topicPublishInfo = MQClientFactory.topicRouteData2TopicPublishInfo(topic, topicRouteData); @@ -129,23 +139,27 @@ public List fetchPublishMessageQueues(String topic) throws MQClien } - public List fetchSubscribeMessageQueues(String topic) throws MQClientException { + public Set fetchSubscribeMessageQueues(String topic) throws MQClientException { try { TopicRouteData topicRouteData = - this.mQClientFactory.getMQClientAPIImpl().getTopicRouteInfoFromNameServer(topic, 1000 * 3); + this.mQClientFactory.getMQClientAPIImpl() + .getTopicRouteInfoFromNameServer(topic, 1000 * 3); if (topicRouteData != null) { - List mqList = + Set mqList = MQClientFactory.topicRouteData2TopicSubscribeInfo(topic, topicRouteData); if (!mqList.isEmpty()) { return mqList; } else { - throw new MQClientException("Can not find Message Queue for this topic, " + topic, null); + throw new MQClientException("Can not find Message Queue for this topic, " + topic + + " Namesrv return empty", null); } } } catch (Exception e) { - throw new MQClientException("Can not find Message Queue for this topic, " + topic, e); + throw new MQClientException("Can not find Message Queue for this topic, " + topic + + FAQUrl.suggestTodo(FAQUrl.MQLIST_NOT_EXIST), // + e); } throw new MQClientException("Unknow why, Can not find Message Queue for this topic, " + topic, null); @@ -173,7 +187,7 @@ public long searchOffset(MessageQueue mq, long timestamp) throws MQClientExcepti } - public long getMaxOffset(MessageQueue mq) throws MQClientException { + public long maxOffset(MessageQueue mq) throws MQClientException { String brokerAddr = this.mQClientFactory.findBrokerAddressInPublish(mq.getBrokerName()); if (null == brokerAddr) { this.mQClientFactory.updateTopicRouteInfoFromNameServer(mq.getTopic()); @@ -194,7 +208,7 @@ public long getMaxOffset(MessageQueue mq) throws MQClientException { } - public long getMinOffset(MessageQueue mq) throws MQClientException { + public long minOffset(MessageQueue mq) throws MQClientException { String brokerAddr = this.mQClientFactory.findBrokerAddressInPublish(mq.getBrokerName()); if (null == brokerAddr) { this.mQClientFactory.updateTopicRouteInfoFromNameServer(mq.getTopic()); @@ -215,7 +229,7 @@ public long getMinOffset(MessageQueue mq) throws MQClientException { } - public long getEarliestMsgStoreTime(MessageQueue mq) throws MQClientException { + public long earliestMsgStoreTime(MessageQueue mq) throws MQClientException { String brokerAddr = this.mQClientFactory.findBrokerAddressInPublish(mq.getBrokerName()); if (null == brokerAddr) { this.mQClientFactory.updateTopicRouteInfoFromNameServer(mq.getTopic()); @@ -240,9 +254,8 @@ public MessageExt viewMessage(String msgId) throws RemotingException, MQBrokerEx InterruptedException, MQClientException { try { MessageId messageId = MessageDecoder.decodeMessageId(msgId); - return this.mQClientFactory.getMQClientAPIImpl() - .viewMessage(RemotingUtil.socketAddress2String(messageId.getAddress()), - messageId.getOffset(), 1000 * 3); + return this.mQClientFactory.getMQClientAPIImpl().viewMessage( + RemotingUtil.socketAddress2String(messageId.getAddress()), messageId.getOffset(), 1000 * 3); } catch (UnknownHostException e) { throw new MQClientException("message id illegal", e); @@ -261,7 +274,7 @@ public QueryResult queryMessage(String topic, String key, int maxNum, long begin if (topicRouteData != null) { List brokerAddrs = new LinkedList(); for (BrokerData brokerData : topicRouteData.getBrokerDatas()) { - String addr = brokerData.getOneBrokerAddr(); + String addr = brokerData.selectBrokerAddr(); if (addr != null) { brokerAddrs.add(addr); } @@ -284,57 +297,57 @@ public QueryResult queryMessage(String topic, String key, int maxNum, long begin new InvokeCallback() { @Override public void operationComplete(ResponseFuture responseFuture) { - countDownLatch.countDown(); - RemotingCommand response = responseFuture.getResponseCommand(); - if (response != null) { - switch (response.getCode()) { - case ResponseCode.SUCCESS_VALUE: { - QueryMessageResponseHeader responseHeader = null; - try { - responseHeader = - (QueryMessageResponseHeader) response - .decodeCommandCustomHeader(QueryMessageResponseHeader.class); + try { + RemotingCommand response = responseFuture.getResponseCommand(); + if (response != null) { + switch (response.getCode()) { + case ResponseCode.SUCCESS_VALUE: { + QueryMessageResponseHeader responseHeader = null; + try { + responseHeader = + (QueryMessageResponseHeader) response + .decodeCommandCustomHeader(QueryMessageResponseHeader.class); + } + catch (RemotingCommandException e) { + log.error("decodeCommandCustomHeader exception", e); + return; + } + + List wrappers = + MessageDecoder.decodes( + ByteBuffer.wrap(response.getBody()), true); + + QueryResult qr = + new QueryResult(responseHeader + .getIndexLastUpdateTimestamp(), wrappers); + queryResultList.add(qr); + break; } - catch (RemotingCommandException e) { - // TODO log - return; + default: + log.warn("getResponseCommand failed, {} {}", + response.getCode(), response.getRemark()); + break; } - - List wrappers = - MessageDecoder.decodes( - ByteBuffer.wrap(response.getBody()), true); - - QueryResult qr = - new QueryResult(responseHeader.getIndexLastUpdateTimestamp(), - wrappers); - queryResultList.add(qr); - break; } - default: - // TODO error log - break; + else { + log.warn("getResponseCommand return null"); } } - else { - // TODO log + finally { + countDownLatch.countDown(); } } }); } - catch (RemotingException e) { - // TODO log - } - catch (MQBrokerException e) { - // TODO log - } - catch (InterruptedException e) { - // TODO log - } // end of try + catch (Exception e) { + log.warn("queryMessage exception", e); + }// end of try + } // end of for boolean ok = countDownLatch.await(1000 * 10, TimeUnit.MILLISECONDS); if (!ok) { - // TODO logӡ־ɣпֳܲɹֳʱ + log.warn("queryMessage, maybe some broker failed"); } long indexLastUpdateTimestamp = 0; @@ -344,11 +357,11 @@ public void operationComplete(ResponseFuture responseFuture) { indexLastUpdateTimestamp = qr.getIndexLastUpdateTimestamp(); } - for (MessageExt wrapper : qr.getMessageList()) { - String keys = wrapper.getKeys(); + for (MessageExt msgExt : qr.getMessageList()) { + String keys = msgExt.getKeys(); if (keys != null) { boolean matched = false; - String[] keyArray = keys.split(Message.KEY_SEPARATOR); + String[] keyArray = keys.split(MessageConst.KEY_SEPARATOR); if (keyArray != null) { for (String k : keyArray) { if (key.equals(k)) { @@ -359,10 +372,11 @@ public void operationComplete(ResponseFuture responseFuture) { } if (matched) { - messageList.add(wrapper); + messageList.add(msgExt); } else { - // TODO log + log.warn("queryMessage, client find not matched message {}", + msgExt.toString()); } } } @@ -372,7 +386,6 @@ public void operationComplete(ResponseFuture responseFuture) { return new QueryResult(indexLastUpdateTimestamp, messageList); } else { - // TODO log throw new MQClientException("query operation over, but no message.", null); } } diff --git a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/impl/MQClientAPIImpl.java b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/impl/MQClientAPIImpl.java index c862a7f6..a70914ea 100644 --- a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/impl/MQClientAPIImpl.java +++ b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/impl/MQClientAPIImpl.java @@ -1,44 +1,94 @@ /** - * $Id: MQClientAPIImpl.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.client.impl; +import java.io.UnsupportedEncodingException; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.HashMap; +import java.util.HashSet; import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import org.slf4j.Logger; + +import com.alibaba.rocketmq.client.VirtualEnvUtil; import com.alibaba.rocketmq.client.consumer.PullCallback; import com.alibaba.rocketmq.client.consumer.PullResult; import com.alibaba.rocketmq.client.consumer.PullStatus; import com.alibaba.rocketmq.client.exception.MQBrokerException; import com.alibaba.rocketmq.client.exception.MQClientException; import com.alibaba.rocketmq.client.impl.consumer.PullResultExt; +import com.alibaba.rocketmq.client.log.ClientLogger; import com.alibaba.rocketmq.client.producer.SendCallback; import com.alibaba.rocketmq.client.producer.SendResult; import com.alibaba.rocketmq.client.producer.SendStatus; -import com.alibaba.rocketmq.common.Message; -import com.alibaba.rocketmq.common.MessageDecoder; -import com.alibaba.rocketmq.common.MessageExt; -import com.alibaba.rocketmq.common.MessageQueue; import com.alibaba.rocketmq.common.MQVersion; +import com.alibaba.rocketmq.common.MixAll; import com.alibaba.rocketmq.common.TopicConfig; +import com.alibaba.rocketmq.common.UtilAll; +import com.alibaba.rocketmq.common.admin.ConsumeStats; +import com.alibaba.rocketmq.common.admin.OffsetWrapper; +import com.alibaba.rocketmq.common.admin.TopicOffset; +import com.alibaba.rocketmq.common.admin.TopicStatsTable; +import com.alibaba.rocketmq.common.message.Message; +import com.alibaba.rocketmq.common.message.MessageDecoder; +import com.alibaba.rocketmq.common.message.MessageExt; +import com.alibaba.rocketmq.common.message.MessageQueue; +import com.alibaba.rocketmq.common.namesrv.NamesrvUtil; import com.alibaba.rocketmq.common.namesrv.TopAddressing; import com.alibaba.rocketmq.common.protocol.MQProtos.MQRequestCode; import com.alibaba.rocketmq.common.protocol.MQProtos.MQResponseCode; +import com.alibaba.rocketmq.common.protocol.body.ClusterInfo; +import com.alibaba.rocketmq.common.protocol.body.ConsumerConnection; +import com.alibaba.rocketmq.common.protocol.body.GetConsumerStatusBody; +import com.alibaba.rocketmq.common.protocol.body.KVTable; +import com.alibaba.rocketmq.common.protocol.body.LockBatchRequestBody; +import com.alibaba.rocketmq.common.protocol.body.LockBatchResponseBody; +import com.alibaba.rocketmq.common.protocol.body.ProducerConnection; +import com.alibaba.rocketmq.common.protocol.body.ResetOffsetBody; +import com.alibaba.rocketmq.common.protocol.body.TopicList; +import com.alibaba.rocketmq.common.protocol.body.UnlockBatchRequestBody; +import com.alibaba.rocketmq.common.protocol.header.ConsumerSendMsgBackRequestHeader; import com.alibaba.rocketmq.common.protocol.header.CreateTopicRequestHeader; +import com.alibaba.rocketmq.common.protocol.header.DeleteSubscriptionGroupRequestHeader; +import com.alibaba.rocketmq.common.protocol.header.DeleteTopicRequestHeader; import com.alibaba.rocketmq.common.protocol.header.EndTransactionRequestHeader; +import com.alibaba.rocketmq.common.protocol.header.GetConsumeStatsRequestHeader; +import com.alibaba.rocketmq.common.protocol.header.GetConsumerConnectionListRequestHeader; +import com.alibaba.rocketmq.common.protocol.header.GetConsumerListByGroupRequestHeader; +import com.alibaba.rocketmq.common.protocol.header.GetConsumerListByGroupResponseBody; +import com.alibaba.rocketmq.common.protocol.header.GetConsumerStatusRequestHeader; import com.alibaba.rocketmq.common.protocol.header.GetEarliestMsgStoretimeRequestHeader; import com.alibaba.rocketmq.common.protocol.header.GetEarliestMsgStoretimeResponseHeader; import com.alibaba.rocketmq.common.protocol.header.GetMaxOffsetRequestHeader; import com.alibaba.rocketmq.common.protocol.header.GetMaxOffsetResponseHeader; import com.alibaba.rocketmq.common.protocol.header.GetMinOffsetRequestHeader; import com.alibaba.rocketmq.common.protocol.header.GetMinOffsetResponseHeader; +import com.alibaba.rocketmq.common.protocol.header.GetProducerConnectionListRequestHeader; +import com.alibaba.rocketmq.common.protocol.header.GetTopicStatsInfoRequestHeader; import com.alibaba.rocketmq.common.protocol.header.PullMessageRequestHeader; import com.alibaba.rocketmq.common.protocol.header.PullMessageResponseHeader; import com.alibaba.rocketmq.common.protocol.header.QueryConsumerOffsetRequestHeader; import com.alibaba.rocketmq.common.protocol.header.QueryConsumerOffsetResponseHeader; import com.alibaba.rocketmq.common.protocol.header.QueryMessageRequestHeader; +import com.alibaba.rocketmq.common.protocol.header.ResetOffsetRequestHeader; import com.alibaba.rocketmq.common.protocol.header.SearchOffsetRequestHeader; import com.alibaba.rocketmq.common.protocol.header.SearchOffsetResponseHeader; import com.alibaba.rocketmq.common.protocol.header.SendMessageRequestHeader; @@ -46,75 +96,140 @@ import com.alibaba.rocketmq.common.protocol.header.UnregisterClientRequestHeader; import com.alibaba.rocketmq.common.protocol.header.UpdateConsumerOffsetRequestHeader; import com.alibaba.rocketmq.common.protocol.header.ViewMessageRequestHeader; +import com.alibaba.rocketmq.common.protocol.header.namesrv.DeleteKVConfigRequestHeader; +import com.alibaba.rocketmq.common.protocol.header.namesrv.GetKVConfigRequestHeader; +import com.alibaba.rocketmq.common.protocol.header.namesrv.GetKVConfigResponseHeader; +import com.alibaba.rocketmq.common.protocol.header.namesrv.GetKVListByNamespaceRequestHeader; import com.alibaba.rocketmq.common.protocol.header.namesrv.GetRouteInfoRequestHeader; -import com.alibaba.rocketmq.common.protocol.header.namesrv.RegisterOrderTopicRequestHeader; +import com.alibaba.rocketmq.common.protocol.header.namesrv.PutKVConfigRequestHeader; +import com.alibaba.rocketmq.common.protocol.header.namesrv.WipeWritePermOfBrokerRequestHeader; +import com.alibaba.rocketmq.common.protocol.header.namesrv.WipeWritePermOfBrokerResponseHeader; +import com.alibaba.rocketmq.common.protocol.heartbeat.ConsumerData; import com.alibaba.rocketmq.common.protocol.heartbeat.HeartbeatData; -import com.alibaba.rocketmq.common.protocol.route.BrokerData; -import com.alibaba.rocketmq.common.protocol.route.QueueData; +import com.alibaba.rocketmq.common.protocol.heartbeat.ProducerData; +import com.alibaba.rocketmq.common.protocol.heartbeat.SubscriptionData; import com.alibaba.rocketmq.common.protocol.route.TopicRouteData; +import com.alibaba.rocketmq.common.subscription.SubscriptionGroupConfig; import com.alibaba.rocketmq.remoting.InvokeCallback; import com.alibaba.rocketmq.remoting.RemotingClient; +import com.alibaba.rocketmq.remoting.common.RemotingHelper; +import com.alibaba.rocketmq.remoting.common.RemotingUtil; import com.alibaba.rocketmq.remoting.exception.RemotingCommandException; +import com.alibaba.rocketmq.remoting.exception.RemotingConnectException; import com.alibaba.rocketmq.remoting.exception.RemotingException; +import com.alibaba.rocketmq.remoting.exception.RemotingSendRequestException; +import com.alibaba.rocketmq.remoting.exception.RemotingTimeoutException; +import com.alibaba.rocketmq.remoting.exception.RemotingTooMuchRequestException; import com.alibaba.rocketmq.remoting.netty.NettyClientConfig; import com.alibaba.rocketmq.remoting.netty.NettyRemotingClient; import com.alibaba.rocketmq.remoting.netty.ResponseFuture; import com.alibaba.rocketmq.remoting.protocol.RemotingCommand; +import com.alibaba.rocketmq.remoting.protocol.RemotingProtos; import com.alibaba.rocketmq.remoting.protocol.RemotingProtos.ResponseCode; -import com.google.protobuf.InvalidProtocolBufferException; +import com.alibaba.rocketmq.remoting.protocol.RemotingSerializable; /** - * װͨŲAPI - * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * 封装所有与服务器通信部分API * + * @author shijia.wxr + * @since 2013-7-24 */ public class MQClientAPIImpl { + private final static Logger log = ClientLogger.getLog(); private final RemotingClient remotingClient; private final TopAddressing topAddressing = new TopAddressing(); - private String nameSrvAddr = null; - private final ClientRemotingProcessor clientRemotingProcessor; + private String nameSrvAddr = null; + // 虚拟运行环境相关的project group + private String projectGroupPrefix; static { System.setProperty(RemotingCommand.RemotingVersionKey, Integer.toString(MQVersion.CurrentVersion)); } + public String getProjectGroupPrefix() { + return projectGroupPrefix; + } + + public MQClientAPIImpl(final NettyClientConfig nettyClientConfig, final ClientRemotingProcessor clientRemotingProcessor) { this.remotingClient = new NettyRemotingClient(nettyClientConfig); this.clientRemotingProcessor = clientRemotingProcessor; /** - * עͻֵ֧RPC CODE + * 注册客户端支持的RPC CODE */ this.remotingClient.registerProcessor(MQRequestCode.CHECK_TRANSACTION_STATE_VALUE, this.clientRemotingProcessor, null); + + this.remotingClient.registerProcessor(MQRequestCode.NOTIFY_CONSUMER_IDS_CHANGED_VALUE, + this.clientRemotingProcessor, null); + + this.remotingClient.registerProcessor(MQRequestCode.RESET_CONSUMER_CLIENT_OFFSET_VALUE, + this.clientRemotingProcessor, null); + + this.remotingClient.registerProcessor(MQRequestCode.GET_CONSUMER_STATUS_FROM_CLIENT_VALUE, + this.clientRemotingProcessor, null); + } + + + public List getNameServerAddressList() { + return this.remotingClient.getNameServerAddressList(); + } + + + public RemotingClient getRemotingClient() { + return remotingClient; } - public void fetchNameServerAddr() { + public String fetchNameServerAddr() { try { String addrs = this.topAddressing.fetchNSAddr(); if (addrs != null) { if (!addrs.equals(this.nameSrvAddr)) { - // log.info("name server address changed, old: " + - // this.nameSrvAddr + " new: " + addrs); + log.info("name server address changed, old: " + this.nameSrvAddr + " new: " + addrs); this.updateNameServerAddressList(addrs); this.nameSrvAddr = addrs; + return nameSrvAddr; } } } catch (Exception e) { - // log.error(e); + log.error("fetchNameServerAddr Exception", e); + } + return nameSrvAddr; + } + + + public void updateNameServerAddressList(final String addrs) { + List lst = new ArrayList(); + String[] addrArray = addrs.split(";"); + if (addrArray != null) { + for (String addr : addrArray) { + lst.add(addr); + } + + this.remotingClient.updateNameServerAddressList(lst); } } public void start() { + // 远程通信 Client 启动 this.remotingClient.start(); + + // 获取虚拟运行环境相关的project group + try { + String localAddress = RemotingUtil.getLocalAddress(); + projectGroupPrefix = this.getProjectGroupByIp(localAddress, 3000); + log.info("The client[{}] in project group: {}", localAddress, projectGroupPrefix); + } + catch (Exception e) { + } } @@ -123,24 +238,49 @@ public void shutdown() { } - public void updateNameServerAddressList(final String addrs) { - List lst = new ArrayList(); - String[] addrArray = addrs.split(";"); - if (addrArray != null) { - for (String addr : addrArray) { - lst.add(addr); - } + public void createSubscriptionGroup(final String addr, final SubscriptionGroupConfig config, + final long timeoutMillis) throws RemotingException, MQBrokerException, InterruptedException, + MQClientException { + // 添加虚拟运行环境相关的projectGroupPrefix + if (!UtilAll.isBlank(projectGroupPrefix)) { + config.setGroupName(VirtualEnvUtil.buildWithProjectGroup(config.getGroupName(), + projectGroupPrefix)); + } - this.remotingClient.updateNameServerAddressList(lst); + RemotingCommand request = + RemotingCommand.createRequestCommand(MQRequestCode.UPDATE_AND_CREATE_SUBSCRIPTIONGROUP_VALUE, + null); + + byte[] body = RemotingSerializable.encode(config); + request.setBody(body); + + RemotingCommand response = this.remotingClient.invokeSync(addr, request, timeoutMillis); + assert response != null; + switch (response.getCode()) { + case ResponseCode.SUCCESS_VALUE: { + return; + } + default: + break; } + + throw new MQClientException(response.getCode(), response.getRemark()); + } public void createTopic(final String addr, final String defaultTopic, final TopicConfig topicConfig, final long timeoutMillis) throws RemotingException, MQBrokerException, InterruptedException, MQClientException { + // 添加虚拟运行环境相关的projectGroupPrefix + String topicWithProjectGroup = topicConfig.getTopicName(); + if (!UtilAll.isBlank(projectGroupPrefix)) { + topicWithProjectGroup = + VirtualEnvUtil.buildWithProjectGroup(topicConfig.getTopicName(), projectGroupPrefix); + } + CreateTopicRequestHeader requestHeader = new CreateTopicRequestHeader(); - requestHeader.setTopic(topicConfig.getTopicName()); + requestHeader.setTopic(topicWithProjectGroup); requestHeader.setDefaultTopic(defaultTopic); requestHeader.setReadQueueNums(topicConfig.getReadQueueNums()); requestHeader.setWriteQueueNums(topicConfig.getWriteQueueNums()); @@ -148,7 +288,8 @@ public void createTopic(final String addr, final String defaultTopic, final Topi requestHeader.setTopicFilterType(topicConfig.getTopicFilterType().name()); RemotingCommand request = - RemotingCommand.createRequestCommand(MQRequestCode.UPDATE_AND_CREATE_TOPIC_VALUE, requestHeader); + RemotingCommand.createRequestCommand(MQRequestCode.UPDATE_AND_CREATE_TOPIC_VALUE, + requestHeader); RemotingCommand response = this.remotingClient.invokeSync(addr, request, timeoutMillis); assert response != null; @@ -164,6 +305,62 @@ public void createTopic(final String addr, final String defaultTopic, final Topi } + /** + * 发送消息 + */ + public SendResult sendMessage(// + final String addr,// 1 + final String brokerName,// 2 + final Message msg,// 3 + final SendMessageRequestHeader requestHeader,// 4 + final long timeoutMillis,// 5 + final CommunicationMode communicationMode,// 6 + final SendCallback sendCallback// 7 + ) throws RemotingException, MQBrokerException, InterruptedException { + // 添加虚拟运行环境相关的projectGroupPrefix + if (!UtilAll.isBlank(projectGroupPrefix)) { + msg.setTopic(VirtualEnvUtil.buildWithProjectGroup(msg.getTopic(), projectGroupPrefix)); + requestHeader.setProducerGroup(VirtualEnvUtil.buildWithProjectGroup( + requestHeader.getProducerGroup(), projectGroupPrefix)); + requestHeader.setTopic(VirtualEnvUtil.buildWithProjectGroup(requestHeader.getTopic(), + projectGroupPrefix)); + } + + RemotingCommand request = + RemotingCommand.createRequestCommand(MQRequestCode.SEND_MESSAGE_VALUE, requestHeader); + request.setBody(msg.getBody()); + + switch (communicationMode) { + case ONEWAY: + this.remotingClient.invokeOneway(addr, request, timeoutMillis); + return null; + case ASYNC: + this.sendMessageAsync(addr, brokerName, msg, timeoutMillis, request, sendCallback); + return null; + case SYNC: + return this.sendMessageSync(addr, brokerName, msg, timeoutMillis, request); + default: + assert false; + break; + } + + return null; + } + + + private SendResult sendMessageSync(// + final String addr,// + final String brokerName,// + final Message msg,// + final long timeoutMillis,// + final RemotingCommand request// + ) throws RemotingException, MQBrokerException, InterruptedException { + RemotingCommand response = this.remotingClient.invokeSync(addr, request, timeoutMillis); + assert response != null; + return this.processSendResponse(brokerName, msg, response); + } + + private void sendMessageAsync(// final String addr,// final String brokerName,// @@ -196,11 +393,12 @@ public void operationComplete(ResponseFuture responseFuture) { .getCause())); } else if (responseFuture.isTimeout()) { - sendCallback.onException(new MQClientException("wait response timeout", responseFuture - .getCause())); + sendCallback.onException(new MQClientException("wait response timeout " + + responseFuture.getTimeoutMillis() + "ms", responseFuture.getCause())); } else { - sendCallback.onException(new MQClientException("unknow reseaon", responseFuture.getCause())); + sendCallback.onException(new MQClientException("unknow reseaon", responseFuture + .getCause())); } } } @@ -243,9 +441,11 @@ private SendResult processSendResponse(// (SendMessageResponseHeader) response .decodeCommandCustomHeader(SendMessageResponseHeader.class); - MessageQueue messageQueue = new MessageQueue(msg.getTopic(), brokerName, responseHeader.getQueueId()); + MessageQueue messageQueue = + new MessageQueue(msg.getTopic(), brokerName, responseHeader.getQueueId()); + return new SendResult(sendStatus, responseHeader.getMsgId(), messageQueue, - responseHeader.getQueueOffset()); + responseHeader.getQueueOffset(), projectGroupPrefix); } default: break; @@ -255,44 +455,36 @@ private SendResult processSendResponse(// } - private SendResult sendMessageSync(// + /** + * 拉消息接口 + */ + public PullResult pullMessage(// final String addr,// - final String brokerName,// - final Message msg,// + final PullMessageRequestHeader requestHeader,// final long timeoutMillis,// - final RemotingCommand request// + final CommunicationMode communicationMode,// + final PullCallback pullCallback// ) throws RemotingException, MQBrokerException, InterruptedException { - RemotingCommand response = this.remotingClient.invokeSync(addr, request, timeoutMillis); - assert response != null; - return this.processSendResponse(brokerName, msg, response); - } - + // 添加虚拟运行环境相关的projectGroupPrefix + if (!UtilAll.isBlank(projectGroupPrefix)) { + requestHeader.setConsumerGroup(VirtualEnvUtil.buildWithProjectGroup( + requestHeader.getConsumerGroup(), projectGroupPrefix)); + requestHeader.setTopic(VirtualEnvUtil.buildWithProjectGroup(requestHeader.getTopic(), + projectGroupPrefix)); + } - /** - * Ϣ - */ - public SendResult sendMessage(// - final String addr,// 1 - final String brokerName,// 2 - final Message msg,// 3 - final SendMessageRequestHeader requestHeader,// 4 - final long timeoutMillis,// 5 - final CommunicationMode communicationMode,// 6 - final SendCallback sendCallback// 7 - ) throws RemotingException, MQBrokerException, InterruptedException { RemotingCommand request = - RemotingCommand.createRequestCommand(MQRequestCode.SEND_MESSAGE_VALUE, requestHeader); - request.setBody(msg.getBody()); + RemotingCommand.createRequestCommand(MQRequestCode.PULL_MESSAGE_VALUE, requestHeader); switch (communicationMode) { case ONEWAY: - this.remotingClient.invokeOneway(addr, request, timeoutMillis); + assert false; return null; case ASYNC: - this.sendMessageAsync(addr, brokerName, msg, timeoutMillis, request, sendCallback); + this.pullMessageAsync(addr, request, timeoutMillis, pullCallback); return null; case SYNC: - return this.sendMessageSync(addr, brokerName, msg, timeoutMillis, request); + return this.pullMessageSync(addr, request, timeoutMillis); default: assert false; break; @@ -302,46 +494,6 @@ public SendResult sendMessage(// } - private PullResult processPullResponse(final RemotingCommand response) throws MQBrokerException, - RemotingCommandException { - PullStatus pullStatus = PullStatus.NO_NEW_MSG; - switch (response.getCode()) { - case ResponseCode.SUCCESS_VALUE: - pullStatus = PullStatus.FOUND; - break; - case MQResponseCode.PULL_NOT_FOUND_VALUE: - pullStatus = PullStatus.NO_NEW_MSG; - break; - case MQResponseCode.PULL_RETRY_IMMEDIATELY_VALUE: - pullStatus = PullStatus.NO_MATCHED_MSG; - break; - case MQResponseCode.PULL_OFFSET_MOVED_VALUE: - pullStatus = PullStatus.OFFSET_ILLEGAL; - break; - - default: - throw new MQBrokerException(response.getCode(), response.getRemark()); - } - - PullMessageResponseHeader responseHeader = - (PullMessageResponseHeader) response.decodeCommandCustomHeader(PullMessageResponseHeader.class); - - return new PullResultExt(pullStatus, responseHeader.getNextBeginOffset(), responseHeader.getMinOffset(), - responseHeader.getMaxOffset(), null, responseHeader.getSuggestPullingFromSlave(), response.getBody()); - } - - - private PullResult pullMessageSync(// - final String addr,// 1 - final RemotingCommand request,// 2 - final long timeoutMillis// 3 - ) throws RemotingException, InterruptedException, MQBrokerException { - RemotingCommand response = this.remotingClient.invokeSync(addr, request, timeoutMillis); - assert response != null; - return this.processPullResponse(response); - } - - private void pullMessageAsync(// final String addr,// 1 final RemotingCommand request,// @@ -368,11 +520,12 @@ public void operationComplete(ResponseFuture responseFuture) { .getCause())); } else if (responseFuture.isTimeout()) { - pullCallback.onException(new MQClientException("wait response timeout", responseFuture - .getCause())); + pullCallback.onException(new MQClientException("wait response timeout " + + responseFuture.getTimeoutMillis() + "ms", responseFuture.getCause())); } else { - pullCallback.onException(new MQClientException("unknow reseaon", responseFuture.getCause())); + pullCallback.onException(new MQClientException("unknow reseaon", responseFuture + .getCause())); } } } @@ -380,39 +533,50 @@ else if (responseFuture.isTimeout()) { } - /** - * Ϣӿ - */ - public PullResult pullMessage(// - final String addr,// - final PullMessageRequestHeader requestHeader,// - final long timeoutMillis,// - final CommunicationMode communicationMode,// - final PullCallback pullCallback// - ) throws RemotingException, MQBrokerException, InterruptedException { - RemotingCommand request = - RemotingCommand.createRequestCommand(MQRequestCode.PULL_MESSAGE_VALUE, requestHeader); + private PullResult processPullResponse(final RemotingCommand response) throws MQBrokerException, + RemotingCommandException { + PullStatus pullStatus = PullStatus.NO_NEW_MSG; + switch (response.getCode()) { + case ResponseCode.SUCCESS_VALUE: + pullStatus = PullStatus.FOUND; + break; + case MQResponseCode.PULL_NOT_FOUND_VALUE: + pullStatus = PullStatus.NO_NEW_MSG; + break; + case MQResponseCode.PULL_RETRY_IMMEDIATELY_VALUE: + pullStatus = PullStatus.NO_MATCHED_MSG; + break; + case MQResponseCode.PULL_OFFSET_MOVED_VALUE: + pullStatus = PullStatus.OFFSET_ILLEGAL; + break; - switch (communicationMode) { - case ONEWAY: - assert false; - return null; - case ASYNC: - this.pullMessageAsync(addr, request, timeoutMillis, pullCallback); - return null; - case SYNC: - return this.pullMessageSync(addr, request, timeoutMillis); default: - assert false; - break; + throw new MQBrokerException(response.getCode(), response.getRemark()); } - return null; + PullMessageResponseHeader responseHeader = + (PullMessageResponseHeader) response + .decodeCommandCustomHeader(PullMessageResponseHeader.class); + + return new PullResultExt(pullStatus, responseHeader.getNextBeginOffset(), + responseHeader.getMinOffset(), responseHeader.getMaxOffset(), null, + responseHeader.getSuggestWhichBrokerId(), response.getBody()); + } + + + private PullResult pullMessageSync(// + final String addr,// 1 + final RemotingCommand request,// 2 + final long timeoutMillis// 3 + ) throws RemotingException, InterruptedException, MQBrokerException { + RemotingCommand response = this.remotingClient.invokeSync(addr, request, timeoutMillis); + assert response != null; + return this.processPullResponse(response); } /** - * ʱѯOffset + * 根据时间查询Offset */ public MessageExt viewMessage(final String addr, final long phyoffset, final long timeoutMillis) throws RemotingException, MQBrokerException, InterruptedException { @@ -426,7 +590,13 @@ public MessageExt viewMessage(final String addr, final long phyoffset, final lon switch (response.getCode()) { case ResponseCode.SUCCESS_VALUE: { ByteBuffer byteBuffer = ByteBuffer.wrap(response.getBody()); - return MessageDecoder.decode(byteBuffer); + MessageExt messageExt = MessageDecoder.decode(byteBuffer); + // 清除虚拟运行环境相关的projectGroupPrefix + if (!UtilAll.isBlank(projectGroupPrefix)) { + messageExt.setTopic(VirtualEnvUtil.clearProjectGroup(messageExt.getTopic(), + projectGroupPrefix)); + } + return messageExt; } default: break; @@ -437,17 +607,23 @@ public MessageExt viewMessage(final String addr, final long phyoffset, final lon /** - * ʱѯOffset + * 根据时间查询Offset */ public long searchOffset(final String addr, final String topic, final int queueId, final long timestamp, final long timeoutMillis) throws RemotingException, MQBrokerException, InterruptedException { + // 添加虚拟运行环境相关的projectGroupPrefix + String topicWithProjectGroup = topic; + if (!UtilAll.isBlank(projectGroupPrefix)) { + topicWithProjectGroup = VirtualEnvUtil.buildWithProjectGroup(topic, projectGroupPrefix); + } + SearchOffsetRequestHeader requestHeader = new SearchOffsetRequestHeader(); - requestHeader.setTopic(topic); + requestHeader.setTopic(topicWithProjectGroup); requestHeader.setQueueId(queueId); requestHeader.setTimestamp(timestamp); RemotingCommand request = - RemotingCommand - .createRequestCommand(MQRequestCode.SEARCH_OFFSET_BY_TIMESTAMP_VALUE, requestHeader); + RemotingCommand.createRequestCommand(MQRequestCode.SEARCH_OFFSET_BY_TIMESTAMP_VALUE, + requestHeader); RemotingCommand response = this.remotingClient.invokeSync(addr, request, timeoutMillis); assert response != null; @@ -467,12 +643,18 @@ public long searchOffset(final String addr, final String topic, final int queueI /** - * ȡеOffset + * 获取队列的最大Offset */ - public long getMaxOffset(final String addr, final String topic, final int queueId, final long timeoutMillis) - throws RemotingException, MQBrokerException, InterruptedException { + public long getMaxOffset(final String addr, final String topic, final int queueId, + final long timeoutMillis) throws RemotingException, MQBrokerException, InterruptedException { + // 添加虚拟运行环境相关的projectGroupPrefix + String topicWithProjectGroup = topic; + if (!UtilAll.isBlank(projectGroupPrefix)) { + topicWithProjectGroup = VirtualEnvUtil.buildWithProjectGroup(topic, projectGroupPrefix); + } + GetMaxOffsetRequestHeader requestHeader = new GetMaxOffsetRequestHeader(); - requestHeader.setTopic(topic); + requestHeader.setTopic(topicWithProjectGroup); requestHeader.setQueueId(queueId); RemotingCommand request = RemotingCommand.createRequestCommand(MQRequestCode.GET_MAX_OFFSET_VALUE, requestHeader); @@ -496,12 +678,57 @@ public long getMaxOffset(final String addr, final String topic, final int queueI /** - * ȡеСOffset + * 获取某个组的Consumer Id列表 */ - public long getMinOffset(final String addr, final String topic, final int queueId, final long timeoutMillis) - throws RemotingException, MQBrokerException, InterruptedException { - GetMinOffsetRequestHeader requestHeader = new GetMinOffsetRequestHeader(); - requestHeader.setTopic(topic); + public List getConsumerIdListByGroup(// + final String addr, // + final String consumerGroup, // + final long timeoutMillis) throws RemotingConnectException, RemotingSendRequestException, + RemotingTimeoutException, MQBrokerException, InterruptedException { + // 添加虚拟运行环境相关的projectGroupPrefix + String consumerGroupWithProjectGroup = consumerGroup; + if (!UtilAll.isBlank(projectGroupPrefix)) { + consumerGroupWithProjectGroup = + VirtualEnvUtil.buildWithProjectGroup(consumerGroup, projectGroupPrefix); + } + + GetConsumerListByGroupRequestHeader requestHeader = new GetConsumerListByGroupRequestHeader(); + requestHeader.setConsumerGroup(consumerGroupWithProjectGroup); + RemotingCommand request = + RemotingCommand.createRequestCommand(MQRequestCode.GET_CONSUMER_LIST_BY_GROUP_VALUE, + requestHeader); + RemotingCommand response = this.remotingClient.invokeSync(addr, request, timeoutMillis); + assert response != null; + switch (response.getCode()) { + case ResponseCode.SUCCESS_VALUE: { + if (response.getBody() != null) { + GetConsumerListByGroupResponseBody body = + GetConsumerListByGroupResponseBody.decode(response.getBody(), + GetConsumerListByGroupResponseBody.class); + return body.getConsumerIdList(); + } + } + default: + break; + } + + throw new MQBrokerException(response.getCode(), response.getRemark()); + } + + + /** + * 获取队列的最小Offset + */ + public long getMinOffset(final String addr, final String topic, final int queueId, + final long timeoutMillis) throws RemotingException, MQBrokerException, InterruptedException { + // 添加虚拟运行环境相关的projectGroupPrefix + String topicWithProjectGroup = topic; + if (!UtilAll.isBlank(projectGroupPrefix)) { + topicWithProjectGroup = VirtualEnvUtil.buildWithProjectGroup(topic, projectGroupPrefix); + } + + GetMinOffsetRequestHeader requestHeader = new GetMinOffsetRequestHeader(); + requestHeader.setTopic(topicWithProjectGroup); requestHeader.setQueueId(queueId); RemotingCommand request = RemotingCommand.createRequestCommand(MQRequestCode.GET_MIN_OFFSET_VALUE, requestHeader); @@ -525,17 +752,22 @@ public long getMinOffset(final String addr, final String topic, final int queueI /** - * ȡеʱ + * 获取队列的最早时间 */ public long getEarliestMsgStoretime(final String addr, final String topic, final int queueId, final long timeoutMillis) throws RemotingException, MQBrokerException, InterruptedException { + // 添加虚拟运行环境相关的projectGroupPrefix + String topicWithProjectGroup = topic; + if (!UtilAll.isBlank(projectGroupPrefix)) { + topicWithProjectGroup = VirtualEnvUtil.buildWithProjectGroup(topic, projectGroupPrefix); + } GetEarliestMsgStoretimeRequestHeader requestHeader = new GetEarliestMsgStoretimeRequestHeader(); - requestHeader.setTopic(topic); + requestHeader.setTopic(topicWithProjectGroup); requestHeader.setQueueId(queueId); RemotingCommand request = - RemotingCommand - .createRequestCommand(MQRequestCode.GET_EARLIEST_MSG_STORETIME_VALUE, requestHeader); + RemotingCommand.createRequestCommand(MQRequestCode.GET_EARLIEST_MSG_STORETIME_VALUE, + requestHeader); RemotingCommand response = this.remotingClient.invokeSync(addr, request, timeoutMillis); assert response != null; @@ -556,15 +788,24 @@ public long getEarliestMsgStoretime(final String addr, final String topic, final /** - * ѯConsumerѽ + * 查询Consumer消费进度 */ public long queryConsumerOffset(// final String addr,// final QueryConsumerOffsetRequestHeader requestHeader,// final long timeoutMillis// ) throws RemotingException, MQBrokerException, InterruptedException { + // 添加虚拟运行环境相关的projectGroupPrefix + if (!UtilAll.isBlank(projectGroupPrefix)) { + requestHeader.setConsumerGroup(VirtualEnvUtil.buildWithProjectGroup( + requestHeader.getConsumerGroup(), projectGroupPrefix)); + requestHeader.setTopic(VirtualEnvUtil.buildWithProjectGroup(requestHeader.getTopic(), + projectGroupPrefix)); + } + RemotingCommand request = - RemotingCommand.createRequestCommand(MQRequestCode.QUERY_CONSUMER_OFFSET_VALUE, requestHeader); + RemotingCommand + .createRequestCommand(MQRequestCode.QUERY_CONSUMER_OFFSET_VALUE, requestHeader); RemotingCommand response = this.remotingClient.invokeSync(addr, request, timeoutMillis); assert response != null; switch (response.getCode()) { @@ -584,15 +825,24 @@ public long queryConsumerOffset(// /** - * Consumerѽ + * 更新Consumer消费进度 */ public void updateConsumerOffset(// final String addr,// final UpdateConsumerOffsetRequestHeader requestHeader,// final long timeoutMillis// ) throws RemotingException, MQBrokerException, InterruptedException { + // 添加虚拟运行环境相关的projectGroupPrefix + if (!UtilAll.isBlank(projectGroupPrefix)) { + requestHeader.setConsumerGroup(VirtualEnvUtil.buildWithProjectGroup( + requestHeader.getConsumerGroup(), projectGroupPrefix)); + requestHeader.setTopic(VirtualEnvUtil.buildWithProjectGroup(requestHeader.getTopic(), + projectGroupPrefix)); + } + RemotingCommand request = - RemotingCommand.createRequestCommand(MQRequestCode.UPDATE_CONSUMER_OFFSET_VALUE, requestHeader); + RemotingCommand.createRequestCommand(MQRequestCode.UPDATE_CONSUMER_OFFSET_VALUE, + requestHeader); RemotingCommand response = this.remotingClient.invokeSync(addr, request, timeoutMillis); assert response != null; switch (response.getCode()) { @@ -608,13 +858,63 @@ public void updateConsumerOffset(// /** - * + * 更新Consumer消费进度 + * + * @throws InterruptedException + * @throws RemotingSendRequestException + * @throws RemotingTimeoutException + * @throws RemotingTooMuchRequestException + * + * @throws RemotingConnectException + */ + public void updateConsumerOffsetOneway(// + final String addr,// + final UpdateConsumerOffsetRequestHeader requestHeader,// + final long timeoutMillis// + ) throws RemotingConnectException, RemotingTooMuchRequestException, RemotingTimeoutException, + RemotingSendRequestException, InterruptedException { + // 添加虚拟运行环境相关的projectGroupPrefix + if (!UtilAll.isBlank(projectGroupPrefix)) { + requestHeader.setConsumerGroup(VirtualEnvUtil.buildWithProjectGroup( + requestHeader.getConsumerGroup(), projectGroupPrefix)); + requestHeader.setTopic(VirtualEnvUtil.buildWithProjectGroup(requestHeader.getTopic(), + projectGroupPrefix)); + } + + RemotingCommand request = + RemotingCommand.createRequestCommand(MQRequestCode.UPDATE_CONSUMER_OFFSET_VALUE, + requestHeader); + this.remotingClient.invokeOneway(addr, request, timeoutMillis); + } + + + /** + * 发送心跳 */ public void sendHearbeat(// final String addr,// final HeartbeatData heartbeatData,// final long timeoutMillis// ) throws RemotingException, MQBrokerException, InterruptedException { + // 添加虚拟运行环境相关的projectGroupPrefix + if (!UtilAll.isBlank(projectGroupPrefix)) { + Set consumerDatas = heartbeatData.getConsumerDataSet(); + for (ConsumerData consumerData : consumerDatas) { + consumerData.setGroupName(VirtualEnvUtil.buildWithProjectGroup(consumerData.getGroupName(), + projectGroupPrefix)); + Set subscriptionDatas = consumerData.getSubscriptionDataSet(); + for (SubscriptionData subscriptionData : subscriptionDatas) { + subscriptionData.setTopic(VirtualEnvUtil.buildWithProjectGroup( + subscriptionData.getTopic(), projectGroupPrefix)); + } + } + Set producerDatas = heartbeatData.getProducerDataSet(); + for (ProducerData producerData : producerDatas) { + producerData.setGroupName(VirtualEnvUtil.buildWithProjectGroup(producerData.getGroupName(), + projectGroupPrefix)); + } + } + RemotingCommand request = RemotingCommand.createRequestCommand(MQRequestCode.HEART_BEAT_VALUE, null); request.setBody(heartbeatData.encode()); RemotingCommand response = this.remotingClient.invokeSync(addr, request, timeoutMillis); @@ -632,7 +932,7 @@ public void sendHearbeat(// /** - * + * 发送心跳 */ public void unregisterClient(// final String addr,// @@ -641,10 +941,20 @@ public void unregisterClient(// final String consumerGroup,// final long timeoutMillis// ) throws RemotingException, MQBrokerException, InterruptedException { + // 添加虚拟运行环境相关的projectGroupPrefix + String producerGroupWithProjectGroup = producerGroup; + String consumerGroupWithProjectGroup = consumerGroup; + if (!UtilAll.isBlank(projectGroupPrefix)) { + producerGroupWithProjectGroup = + VirtualEnvUtil.buildWithProjectGroup(producerGroup, projectGroupPrefix); + consumerGroupWithProjectGroup = + VirtualEnvUtil.buildWithProjectGroup(consumerGroup, projectGroupPrefix); + } + final UnregisterClientRequestHeader requestHeader = new UnregisterClientRequestHeader(); requestHeader.setClientID(clientID); - requestHeader.setProducerGroup(producerGroup); - requestHeader.setConsumerGroup(consumerGroup); + requestHeader.setProducerGroup(producerGroupWithProjectGroup); + requestHeader.setConsumerGroup(consumerGroupWithProjectGroup); RemotingCommand request = RemotingCommand.createRequestCommand(MQRequestCode.UNREGISTER_CLIENT_VALUE, requestHeader); RemotingCommand response = this.remotingClient.invokeSync(addr, request, timeoutMillis); @@ -662,31 +972,29 @@ public void unregisterClient(// /** - * Consumerѽ + * 提交或者回滚事务 */ - public void endTransaction(// + public void endTransactionOneway(// final String addr,// final EndTransactionRequestHeader requestHeader,// + final String remark,// final long timeoutMillis// ) throws RemotingException, MQBrokerException, InterruptedException { - RemotingCommand request = - RemotingCommand.createRequestCommand(MQRequestCode.END_TRANSACTION_VALUE, requestHeader); - RemotingCommand response = this.remotingClient.invokeSync(addr, request, timeoutMillis); - assert response != null; - switch (response.getCode()) { - case ResponseCode.SUCCESS_VALUE: { - return; - } - default: - break; + // 添加虚拟运行环境相关的projectGroupPrefix + if (!UtilAll.isBlank(projectGroupPrefix)) { + requestHeader.setProducerGroup(VirtualEnvUtil.buildWithProjectGroup( + requestHeader.getProducerGroup(), projectGroupPrefix)); } - throw new MQBrokerException(response.getCode(), response.getRemark()); + RemotingCommand request = + RemotingCommand.createRequestCommand(MQRequestCode.END_TRANSACTION_VALUE, requestHeader); + request.setRemark(remark); + this.remotingClient.invokeOneway(addr, request, timeoutMillis); } /** - * ѯϢ + * 查询消息 */ public void queryMessage(// final String addr,// @@ -694,6 +1002,12 @@ public void queryMessage(// final long timeoutMillis,// final InvokeCallback invokeCallback// ) throws RemotingException, MQBrokerException, InterruptedException { + // 添加虚拟运行环境相关的projectGroupPrefix + if (!UtilAll.isBlank(projectGroupPrefix)) { + requestHeader.setTopic(VirtualEnvUtil.buildWithProjectGroup(requestHeader.getTopic(), + projectGroupPrefix)); + } + RemotingCommand request = RemotingCommand.createRequestCommand(MQRequestCode.QUERY_MESSAGE_VALUE, requestHeader); this.remotingClient.invokeAsync(addr, request, timeoutMillis, invokeCallback); @@ -702,6 +1016,25 @@ public void queryMessage(// public boolean registerClient(final String addr, final HeartbeatData heartbeat, final long timeoutMillis) throws RemotingException, InterruptedException { + // 添加虚拟运行环境相关的projectGroupPrefix + if (!UtilAll.isBlank(projectGroupPrefix)) { + Set consumerDatas = heartbeat.getConsumerDataSet(); + for (ConsumerData consumerData : consumerDatas) { + consumerData.setGroupName(VirtualEnvUtil.buildWithProjectGroup(consumerData.getGroupName(), + projectGroupPrefix)); + Set subscriptionDatas = consumerData.getSubscriptionDataSet(); + for (SubscriptionData subscriptionData : subscriptionDatas) { + subscriptionData.setTopic(VirtualEnvUtil.buildWithProjectGroup( + subscriptionData.getTopic(), projectGroupPrefix)); + } + } + Set producerDatas = heartbeat.getProducerDataSet(); + for (ProducerData producerData : producerDatas) { + producerData.setGroupName(VirtualEnvUtil.buildWithProjectGroup(producerData.getGroupName(), + projectGroupPrefix)); + } + } + RemotingCommand request = RemotingCommand.createRequestCommand(MQRequestCode.HEART_BEAT_VALUE, null); request.setBody(heartbeat.encode()); RemotingCommand response = this.remotingClient.invokeSync(addr, request, timeoutMillis); @@ -710,85 +1043,817 @@ public boolean registerClient(final String addr, final HeartbeatData heartbeat, /** - * Name ServerȡTopic·Ϣ + * 失败的消息发回Broker */ - public TopicRouteData getTopicRouteInfoFromNameServer_real(final String topic, final long timeoutMillis) - throws RemotingException, MQClientException, InterruptedException, InvalidProtocolBufferException { - GetRouteInfoRequestHeader requestHeader = new GetRouteInfoRequestHeader(); - requestHeader.setTopic(topic); + public void consumerSendMessageBack(// + final MessageExt msg,// + final String consumerGroup,// + final int delayLevel,// + final long timeoutMillis// + ) throws RemotingException, MQBrokerException, InterruptedException { + // 添加虚拟运行环境相关的projectGroupPrefix + String consumerGroupWithProjectGroup = consumerGroup; + if (!UtilAll.isBlank(projectGroupPrefix)) { + consumerGroupWithProjectGroup = + VirtualEnvUtil.buildWithProjectGroup(consumerGroup, projectGroupPrefix); + msg.setTopic(VirtualEnvUtil.buildWithProjectGroup(msg.getTopic(), projectGroupPrefix)); + } + ConsumerSendMsgBackRequestHeader requestHeader = new ConsumerSendMsgBackRequestHeader(); RemotingCommand request = - RemotingCommand.createRequestCommand(MQRequestCode.GET_ROUTEINTO_BY_TOPIC_VALUE, requestHeader); + RemotingCommand.createRequestCommand(MQRequestCode.CONSUMER_SEND_MSG_BACK_VALUE, + requestHeader); + requestHeader.setGroup(consumerGroupWithProjectGroup); + requestHeader.setOffset(msg.getCommitLogOffset()); + requestHeader.setDelayLevel(delayLevel); - RemotingCommand response = this.remotingClient.invokeSync(null, request, timeoutMillis); + String addr = RemotingHelper.parseSocketAddressAddr(msg.getStoreHost()); + + RemotingCommand response = this.remotingClient.invokeSync(addr, request, timeoutMillis); assert response != null; switch (response.getCode()) { - case MQResponseCode.TOPIC_NOT_EXIST_VALUE: { - // TODO LOG + case ResponseCode.SUCCESS_VALUE: { + return; + } + default: break; } + + throw new MQBrokerException(response.getCode(), response.getRemark()); + } + + + public Set lockBatchMQ(// + final String addr,// + final LockBatchRequestBody requestBody,// + final long timeoutMillis) throws RemotingException, MQBrokerException, InterruptedException { + // 添加虚拟运行环境相关的projectGroupPrefix + if (!UtilAll.isBlank(projectGroupPrefix)) { + requestBody.setConsumerGroup((VirtualEnvUtil.buildWithProjectGroup( + requestBody.getConsumerGroup(), projectGroupPrefix))); + Set messageQueues = requestBody.getMqSet(); + for (MessageQueue messageQueue : messageQueues) { + messageQueue.setTopic(VirtualEnvUtil.buildWithProjectGroup(messageQueue.getTopic(), + projectGroupPrefix)); + } + } + + RemotingCommand request = + RemotingCommand.createRequestCommand(MQRequestCode.LOCK_BATCH_MQ_VALUE, null); + request.setBody(requestBody.encode()); + RemotingCommand response = this.remotingClient.invokeSync(addr, request, timeoutMillis); + switch (response.getCode()) { case ResponseCode.SUCCESS_VALUE: { - byte[] body = response.getBody(); - if (body != null) { - return TopicRouteData.decode(body); + LockBatchResponseBody responseBody = + LockBatchResponseBody.decode(response.getBody(), LockBatchResponseBody.class); + Set messageQueues = responseBody.getLockOKMQSet(); + // 清除虚拟运行环境相关的projectGroupPrefix + if (!UtilAll.isBlank(projectGroupPrefix)) { + for (MessageQueue messageQueue : messageQueues) { + messageQueue.setTopic(VirtualEnvUtil.clearProjectGroup(messageQueue.getTopic(), + projectGroupPrefix)); + } } + return messageQueues; } default: break; } - throw new MQClientException(response.getCode(), response.getRemark()); + throw new MQBrokerException(response.getCode(), response.getRemark()); + } + + + public void unlockBatchMQ(// + final String addr,// + final UnlockBatchRequestBody requestBody,// + final long timeoutMillis,// + final boolean oneway// + ) throws RemotingException, MQBrokerException, InterruptedException { + // 添加虚拟运行环境相关的projectGroupPrefix + if (!UtilAll.isBlank(projectGroupPrefix)) { + requestBody.setConsumerGroup(VirtualEnvUtil.buildWithProjectGroup(requestBody.getConsumerGroup(), + projectGroupPrefix)); + Set messageQueues = requestBody.getMqSet(); + for (MessageQueue messageQueue : messageQueues) { + messageQueue.setTopic(VirtualEnvUtil.buildWithProjectGroup(messageQueue.getTopic(), + projectGroupPrefix)); + } + } + + RemotingCommand request = + RemotingCommand.createRequestCommand(MQRequestCode.UNLOCK_BATCH_MQ_VALUE, null); + request.setBody(requestBody.encode()); + + if (oneway) { + this.remotingClient.invokeOneway(addr, request, timeoutMillis); + } + else { + RemotingCommand response = this.remotingClient.invokeSync(addr, request, timeoutMillis); + switch (response.getCode()) { + case ResponseCode.SUCCESS_VALUE: { + return; + } + default: + break; + } + + throw new MQBrokerException(response.getCode(), response.getRemark()); + } + } + + + public TopicStatsTable getTopicStatsInfo(final String addr, final String topic, final long timeoutMillis) + throws InterruptedException, RemotingTimeoutException, RemotingSendRequestException, + RemotingConnectException, MQBrokerException { + // 添加虚拟运行环境相关的projectGroupPrefix + String topicWithProjectGroup = topic; + if (!UtilAll.isBlank(projectGroupPrefix)) { + topicWithProjectGroup = VirtualEnvUtil.buildWithProjectGroup(topic, projectGroupPrefix); + } + + GetTopicStatsInfoRequestHeader requestHeader = new GetTopicStatsInfoRequestHeader(); + requestHeader.setTopic(topicWithProjectGroup); + + RemotingCommand request = + RemotingCommand.createRequestCommand(MQRequestCode.GET_TOPIC_STATS_INFO_VALUE, requestHeader); + RemotingCommand response = this.remotingClient.invokeSync(addr, request, timeoutMillis); + switch (response.getCode()) { + case ResponseCode.SUCCESS_VALUE: { + TopicStatsTable topicStatsTable = + TopicStatsTable.decode(response.getBody(), TopicStatsTable.class); + // 清除虚拟运行环境相关的projectGroupPrefix + if (!UtilAll.isBlank(projectGroupPrefix)) { + HashMap newTopicOffsetMap = + new HashMap(); + for (Map.Entry messageQueue : topicStatsTable.getOffsetTable() + .entrySet()) { + MessageQueue key = messageQueue.getKey(); + key.setTopic(VirtualEnvUtil.clearProjectGroup(key.getTopic(), projectGroupPrefix)); + newTopicOffsetMap.put(key, messageQueue.getValue()); + } + topicStatsTable.setOffsetTable(newTopicOffsetMap); + } + return topicStatsTable; + } + default: + break; + } + + throw new MQBrokerException(response.getCode(), response.getRemark()); + } + + + public ConsumeStats getConsumeStats(final String addr, final String consumerGroup, + final long timeoutMillis) throws InterruptedException, RemotingTimeoutException, + RemotingSendRequestException, RemotingConnectException, MQBrokerException { + // 添加虚拟运行环境相关的projectGroupPrefix + String consumerGroupWithProjectGroup = consumerGroup; + if (!UtilAll.isBlank(projectGroupPrefix)) { + consumerGroupWithProjectGroup = + VirtualEnvUtil.buildWithProjectGroup(consumerGroup, projectGroupPrefix); + } + + GetConsumeStatsRequestHeader requestHeader = new GetConsumeStatsRequestHeader(); + requestHeader.setConsumerGroup(consumerGroupWithProjectGroup); + + RemotingCommand request = + RemotingCommand.createRequestCommand(MQRequestCode.GET_CONSUME_STATS_VALUE, requestHeader); + RemotingCommand response = this.remotingClient.invokeSync(addr, request, timeoutMillis); + switch (response.getCode()) { + case ResponseCode.SUCCESS_VALUE: { + ConsumeStats consumeStats = ConsumeStats.decode(response.getBody(), ConsumeStats.class); + // 清除虚拟运行环境相关的projectGroupPrefix + if (!UtilAll.isBlank(projectGroupPrefix)) { + HashMap newTopicOffsetMap = + new HashMap(); + for (Map.Entry messageQueue : consumeStats.getOffsetTable() + .entrySet()) { + MessageQueue key = messageQueue.getKey(); + key.setTopic(VirtualEnvUtil.clearProjectGroup(key.getTopic(), projectGroupPrefix)); + newTopicOffsetMap.put(key, messageQueue.getValue()); + } + consumeStats.setOffsetTable(newTopicOffsetMap); + } + + return consumeStats; + } + default: + break; + } + + throw new MQBrokerException(response.getCode(), response.getRemark()); } /** - * ΪԷ񣬿ƹName Server + * 根据ProducerGroup获取Producer连接列表 */ - public TopicRouteData getTopicRouteInfoFromNameServer(final String topic, final long timeoutMillis) - throws RemotingException, MQClientException, InterruptedException, InvalidProtocolBufferException { - TopicRouteData topicRouteData = new TopicRouteData(); - topicRouteData.setOrderTopicConf("dev170021.sqa.cm6:4;"); - List brokerDatas = new ArrayList(); - BrokerData bd = new BrokerData(); + public ProducerConnection getProducerConnectionList(final String addr, final String producerGroup, + final long timeoutMillis) throws RemotingConnectException, RemotingSendRequestException, + RemotingTimeoutException, InterruptedException, MQBrokerException { + // 添加虚拟运行环境相关的projectGroupPrefix + String producerGroupWithProjectGroup = producerGroup; + if (!UtilAll.isBlank(projectGroupPrefix)) { + producerGroupWithProjectGroup = + VirtualEnvUtil.buildWithProjectGroup(producerGroup, projectGroupPrefix); + } + + GetProducerConnectionListRequestHeader requestHeader = new GetProducerConnectionListRequestHeader(); + requestHeader.setProducerGroup(producerGroupWithProjectGroup); + + RemotingCommand request = + RemotingCommand.createRequestCommand(MQRequestCode.GET_PRODUCER_CONNECTION_LIST_VALUE, + requestHeader); + RemotingCommand response = this.remotingClient.invokeSync(addr, request, timeoutMillis); + switch (response.getCode()) { + case ResponseCode.SUCCESS_VALUE: { + return ProducerConnection.decode(response.getBody(), ProducerConnection.class); + } + default: + break; + } + + throw new MQBrokerException(response.getCode(), response.getRemark()); + } + + + /** + * 根据ConsumerGroup获取Consumer连接列表以及订阅关系 + */ + public ConsumerConnection getConsumerConnectionList(final String addr, final String consumerGroup, + final long timeoutMillis) throws RemotingConnectException, RemotingSendRequestException, + RemotingTimeoutException, InterruptedException, MQBrokerException { + // 添加虚拟运行环境相关的projectGroupPrefix + String consumerGroupWithProjectGroup = consumerGroup; + if (!UtilAll.isBlank(projectGroupPrefix)) { + consumerGroupWithProjectGroup = + VirtualEnvUtil.buildWithProjectGroup(consumerGroup, projectGroupPrefix); + } + + GetConsumerConnectionListRequestHeader requestHeader = new GetConsumerConnectionListRequestHeader(); + requestHeader.setConsumerGroup(consumerGroupWithProjectGroup); + + RemotingCommand request = + RemotingCommand.createRequestCommand(MQRequestCode.GET_CONSUMER_CONNECTION_LIST_VALUE, + requestHeader); + RemotingCommand response = this.remotingClient.invokeSync(addr, request, timeoutMillis); + switch (response.getCode()) { + case ResponseCode.SUCCESS_VALUE: { + ConsumerConnection consumerConnection = + ConsumerConnection.decode(response.getBody(), ConsumerConnection.class); + if (!UtilAll.isBlank(projectGroupPrefix)) { + ConcurrentHashMap subscriptionDataConcurrentHashMap = + consumerConnection.getSubscriptionTable(); + for (Map.Entry subscriptionDataEntry : subscriptionDataConcurrentHashMap + .entrySet()) { + SubscriptionData subscriptionData = subscriptionDataEntry.getValue(); + subscriptionDataEntry.getValue().setTopic( + VirtualEnvUtil.clearProjectGroup(subscriptionData.getTopic(), projectGroupPrefix)); + } + } + return consumerConnection; + } + default: + break; + } + + throw new MQBrokerException(response.getCode(), response.getRemark()); + } + + + public KVTable getBrokerRuntimeInfo(final String addr, final long timeoutMillis) + throws RemotingConnectException, RemotingSendRequestException, RemotingTimeoutException, + InterruptedException, MQBrokerException { + + RemotingCommand request = + RemotingCommand.createRequestCommand(MQRequestCode.GET_BROKER_RUNTIME_INFO_VALUE, null); + RemotingCommand response = this.remotingClient.invokeSync(addr, request, timeoutMillis); + switch (response.getCode()) { + case ResponseCode.SUCCESS_VALUE: { + return KVTable.decode(response.getBody(), KVTable.class); + } + default: + break; + } + + throw new MQBrokerException(response.getCode(), response.getRemark()); + } + + + /** + * 更新Broker的配置文件 + * + * @param addr + * @param properties + * @param timeoutMillis + * @throws RemotingConnectException + * @throws RemotingSendRequestException + * @throws RemotingTimeoutException + * @throws InterruptedException + * @throws MQBrokerException + * @throws UnsupportedEncodingException + */ + public void updateBrokerConfig(final String addr, final Properties properties, final long timeoutMillis) + throws RemotingConnectException, RemotingSendRequestException, RemotingTimeoutException, + InterruptedException, MQBrokerException, UnsupportedEncodingException { + + RemotingCommand request = + RemotingCommand.createRequestCommand(MQRequestCode.UPDATE_BROKER_CONFIG_VALUE, null); + + String str = MixAll.properties2String(properties); + if (str != null && str.length() > 0) { + request.setBody(str.getBytes(MixAll.DEFAULT_CHARSET)); + RemotingCommand response = this.remotingClient.invokeSync(addr, request, timeoutMillis); + switch (response.getCode()) { + case ResponseCode.SUCCESS_VALUE: { + return; + } + default: + break; + } + + throw new MQBrokerException(response.getCode(), response.getRemark()); + } + } - HashMap brokerAddrs = new HashMap(); - brokerAddrs.put(0L, "10.235.170.21:10911"); - bd.setBrokerName("dev170021.sqa.cm6"); - bd.setBrokerAddrs(brokerAddrs); + /** + * Name Server: 从Name Server获取集群信息 + */ + public ClusterInfo getBrokerClusterInfo(final long timeoutMillis) throws InterruptedException, + RemotingTimeoutException, RemotingSendRequestException, RemotingConnectException, + MQBrokerException { + RemotingCommand request = + RemotingCommand.createRequestCommand(MQRequestCode.GET_BROKER_CLUSTER_INFO_VALUE, null); - brokerDatas.add(bd); + RemotingCommand response = this.remotingClient.invokeSync(null, request, timeoutMillis); + assert response != null; + switch (response.getCode()) { + case ResponseCode.SUCCESS_VALUE: { + ClusterInfo responseBody = ClusterInfo.decode(response.getBody(), ClusterInfo.class); + return responseBody; + } + default: + break; + } - topicRouteData.setBrokerDatas(brokerDatas); - List queueDatas = new ArrayList(); - QueueData queueData = new QueueData(); - queueData.setBrokerName("dev170021.sqa.cm6"); - queueData.setPerm(6); - queueData.setReadQueueNums(4); - queueData.setWriteQueueNums(4); - queueDatas.add(queueData); - topicRouteData.setQueueDatas(queueDatas); + throw new MQBrokerException(response.getCode(), response.getRemark()); - return topicRouteData; } /** - * Name Serverע˳Ϣ + * Name Server: 从Name Server获取 Default Topic 路由信息 */ - public void registerOrderTopic(final String topic, final String orderTopicString, final long timeoutMillis) + public TopicRouteData getDefaultTopicRouteInfoFromNameServer(final String topic, final long timeoutMillis) throws RemotingException, MQClientException, InterruptedException { - RegisterOrderTopicRequestHeader requestHeader = new RegisterOrderTopicRequestHeader(); + GetRouteInfoRequestHeader requestHeader = new GetRouteInfoRequestHeader(); requestHeader.setTopic(topic); - requestHeader.setOrderTopicString(orderTopicString); + RemotingCommand request = - RemotingCommand.createRequestCommand(MQRequestCode.REGISTER_ORDER_TOPIC_VALUE, requestHeader); + RemotingCommand.createRequestCommand(MQRequestCode.GET_ROUTEINTO_BY_TOPIC_VALUE, + requestHeader); RemotingCommand response = this.remotingClient.invokeSync(null, request, timeoutMillis); assert response != null; switch (response.getCode()) { + case MQResponseCode.TOPIC_NOT_EXIST_VALUE: { + // TODO LOG + break; + } case ResponseCode.SUCCESS_VALUE: { - return; + byte[] body = response.getBody(); + if (body != null) { + return TopicRouteData.decode(body, TopicRouteData.class); + } + } + default: + break; + } + + throw new MQClientException(response.getCode(), response.getRemark()); + } + + + /** + * Name Server: 从Name Server获取Topic路由信息 + */ + public TopicRouteData getTopicRouteInfoFromNameServer(final String topic, final long timeoutMillis) + throws RemotingException, MQClientException, InterruptedException { + // 添加虚拟运行环境相关的projectGroupPrefix + String topicWithProjectGroup = topic; + if (!UtilAll.isBlank(projectGroupPrefix)) { + topicWithProjectGroup = VirtualEnvUtil.buildWithProjectGroup(topic, projectGroupPrefix); + } + + GetRouteInfoRequestHeader requestHeader = new GetRouteInfoRequestHeader(); + requestHeader.setTopic(topicWithProjectGroup); + + RemotingCommand request = + RemotingCommand.createRequestCommand(MQRequestCode.GET_ROUTEINTO_BY_TOPIC_VALUE, + requestHeader); + + RemotingCommand response = this.remotingClient.invokeSync(null, request, timeoutMillis); + assert response != null; + switch (response.getCode()) { + case MQResponseCode.TOPIC_NOT_EXIST_VALUE: { + log.warn("get Topic [{}]RouteInfoFromNameServer is not exist value", topic); + break; + } + case ResponseCode.SUCCESS_VALUE: { + byte[] body = response.getBody(); + if (body != null) { + return TopicRouteData.decode(body, TopicRouteData.class); + } + } + default: + break; + } + + throw new MQClientException(response.getCode(), response.getRemark()); + } + + + /** + * Name Server: 从Name Server获取所有Topic列表 + */ + public TopicList getTopicListFromNameServer(final long timeoutMillis) throws RemotingException, + MQClientException, InterruptedException { + RemotingCommand request = + RemotingCommand.createRequestCommand(MQRequestCode.GET_ALL_TOPIC_LIST_FROM_NAMESERVER_VALUE, + null); + + RemotingCommand response = this.remotingClient.invokeSync(null, request, timeoutMillis); + assert response != null; + switch (response.getCode()) { + case ResponseCode.SUCCESS_VALUE: { + byte[] body = response.getBody(); + if (body != null) { + TopicList topicList = TopicList.decode(body, TopicList.class); + + if (!UtilAll.isBlank(projectGroupPrefix)) { + HashSet newTopicSet = new HashSet(); + for (String topic : topicList.getTopicList()) { + newTopicSet.add(VirtualEnvUtil.clearProjectGroup(topic, projectGroupPrefix)); + } + topicList.setTopicList(newTopicSet); + } + return topicList; + } + } + default: + break; + } + + throw new MQClientException(response.getCode(), response.getRemark()); + } + + + /** + * Name Server: Broker下线前,清除Broker对应的权限 + */ + public int wipeWritePermOfBroker(final String namesrvAddr, String brokerName, final long timeoutMillis) + throws RemotingCommandException, RemotingConnectException, RemotingSendRequestException, + RemotingTimeoutException, InterruptedException, MQClientException { + WipeWritePermOfBrokerRequestHeader requestHeader = new WipeWritePermOfBrokerRequestHeader(); + requestHeader.setBrokerName(brokerName); + + RemotingCommand request = + RemotingCommand.createRequestCommand(MQRequestCode.WIPE_WRITE_PERM_OF_BROKER_VALUE, + requestHeader); + RemotingCommand response = this.remotingClient.invokeSync(namesrvAddr, request, timeoutMillis); + assert response != null; + switch (response.getCode()) { + case ResponseCode.SUCCESS_VALUE: { + WipeWritePermOfBrokerResponseHeader responseHeader = + (WipeWritePermOfBrokerResponseHeader) response + .decodeCommandCustomHeader(WipeWritePermOfBrokerResponseHeader.class); + return responseHeader.getWipeTopicCount(); + } + default: + break; + } + + throw new MQClientException(response.getCode(), response.getRemark()); + } + + + public void deleteTopicInBroker(final String addr, final String topic, final long timeoutMillis) + throws RemotingException, MQBrokerException, InterruptedException, MQClientException { + // 添加虚拟运行环境相关的projectGroupPrefix + String topicWithProjectGroup = topic; + if (!UtilAll.isBlank(projectGroupPrefix)) { + topicWithProjectGroup = VirtualEnvUtil.buildWithProjectGroup(topic, projectGroupPrefix); + } + + DeleteTopicRequestHeader requestHeader = new DeleteTopicRequestHeader(); + requestHeader.setTopic(topicWithProjectGroup); + RemotingCommand request = + RemotingCommand.createRequestCommand(MQRequestCode.DELETE_TOPIC_IN_BROKER_VALUE, + requestHeader); + + RemotingCommand response = this.remotingClient.invokeSync(addr, request, timeoutMillis); + assert response != null; + switch (response.getCode()) { + case ResponseCode.SUCCESS_VALUE: { + return; + } + default: + break; + } + + throw new MQClientException(response.getCode(), response.getRemark()); + } + + + public void deleteTopicInNameServer(final String addr, final String topic, final long timeoutMillis) + throws RemotingException, MQBrokerException, InterruptedException, MQClientException { + // 添加虚拟运行环境相关的projectGroupPrefix + String topicWithProjectGroup = topic; + if (!UtilAll.isBlank(projectGroupPrefix)) { + topicWithProjectGroup = VirtualEnvUtil.buildWithProjectGroup(topic, projectGroupPrefix); + } + + DeleteTopicRequestHeader requestHeader = new DeleteTopicRequestHeader(); + requestHeader.setTopic(topicWithProjectGroup); + RemotingCommand request = + RemotingCommand.createRequestCommand(MQRequestCode.DELETE_TOPIC_IN_NAMESRV_VALUE, + requestHeader); + + RemotingCommand response = this.remotingClient.invokeSync(addr, request, timeoutMillis); + assert response != null; + switch (response.getCode()) { + case ResponseCode.SUCCESS_VALUE: { + return; + } + default: + break; + } + + throw new MQClientException(response.getCode(), response.getRemark()); + } + + + public void deleteSubscriptionGroup(final String addr, final String groupName, final long timeoutMillis) + throws RemotingException, MQBrokerException, InterruptedException, MQClientException { + // 添加虚拟运行环境相关的projectGroupPrefix + String groupWithProjectGroup = groupName; + if (!UtilAll.isBlank(projectGroupPrefix)) { + groupWithProjectGroup = VirtualEnvUtil.buildWithProjectGroup(groupName, projectGroupPrefix); + } + + DeleteSubscriptionGroupRequestHeader requestHeader = new DeleteSubscriptionGroupRequestHeader(); + requestHeader.setGroupName(groupWithProjectGroup); + RemotingCommand request = + RemotingCommand.createRequestCommand(MQRequestCode.DELETE_SUBSCRIPTIONGROUP_VALUE, + requestHeader); + + RemotingCommand response = this.remotingClient.invokeSync(addr, request, timeoutMillis); + assert response != null; + switch (response.getCode()) { + case ResponseCode.SUCCESS_VALUE: { + return; + } + default: + break; + } + + throw new MQClientException(response.getCode(), response.getRemark()); + } + + + /** + * Name Server: 从Namesrv获取KV配置 + */ + public String getKVConfigValue(final String namespace, final String key, final long timeoutMillis) + throws RemotingException, MQClientException, InterruptedException { + GetKVConfigRequestHeader requestHeader = new GetKVConfigRequestHeader(); + requestHeader.setNamespace(namespace); + requestHeader.setKey(key); + + RemotingCommand request = + RemotingCommand.createRequestCommand(MQRequestCode.GET_KV_CONFIG_VALUE, requestHeader); + + RemotingCommand response = this.remotingClient.invokeSync(null, request, timeoutMillis); + assert response != null; + switch (response.getCode()) { + case ResponseCode.SUCCESS_VALUE: { + GetKVConfigResponseHeader responseHeader = + (GetKVConfigResponseHeader) response + .decodeCommandCustomHeader(GetKVConfigResponseHeader.class); + return responseHeader.getValue(); + } + default: + break; + } + + throw new MQClientException(response.getCode(), response.getRemark()); + } + + + /** + * Name Server: 添加KV配置 + */ + public void putKVConfigValue(final String namespace, final String key, final String value, + final long timeoutMillis) throws RemotingException, MQClientException, InterruptedException { + PutKVConfigRequestHeader requestHeader = new PutKVConfigRequestHeader(); + requestHeader.setNamespace(namespace); + requestHeader.setKey(key); + requestHeader.setValue(value); + + RemotingCommand request = + RemotingCommand.createRequestCommand(MQRequestCode.PUT_KV_CONFIG_VALUE, requestHeader); + + RemotingCommand response = this.remotingClient.invokeSync(null, request, timeoutMillis); + assert response != null; + switch (response.getCode()) { + case ResponseCode.SUCCESS_VALUE: { + return; + } + default: + break; + } + + throw new MQClientException(response.getCode(), response.getRemark()); + } + + + /** + * Name Server: 添加KV配置 + */ + public void deleteKVConfigValue(final String namespace, final String key, final long timeoutMillis) + throws RemotingException, MQClientException, InterruptedException { + DeleteKVConfigRequestHeader requestHeader = new DeleteKVConfigRequestHeader(); + requestHeader.setNamespace(namespace); + requestHeader.setKey(key); + + RemotingCommand request = + RemotingCommand.createRequestCommand(MQRequestCode.DELETE_KV_CONFIG_VALUE, requestHeader); + + RemotingCommand response = this.remotingClient.invokeSync(null, request, timeoutMillis); + assert response != null; + switch (response.getCode()) { + case ResponseCode.SUCCESS_VALUE: { + return; + } + default: + break; + } + + throw new MQClientException(response.getCode(), response.getRemark()); + } + + + /** + * Name Server: 通过 server ip 获取 project 信息 + */ + public String getProjectGroupByIp(String ip, final long timeoutMillis) throws RemotingException, + MQClientException, InterruptedException { + return getKVConfigValue(NamesrvUtil.NAMESPACE_PROJECT_CONFIG, ip, timeoutMillis); + } + + + /** + * Name Server: 通过 value 获取所有的 key 信息 + */ + public String getKVConfigByValue(final String namespace, String projectGroup, final long timeoutMillis) + throws RemotingException, MQClientException, InterruptedException { + GetKVConfigRequestHeader requestHeader = new GetKVConfigRequestHeader(); + requestHeader.setNamespace(namespace); + requestHeader.setKey(projectGroup); + + RemotingCommand request = + RemotingCommand.createRequestCommand(MQRequestCode.GET_KV_CONFIG_BY_VALUE_VALUE, + requestHeader); + + RemotingCommand response = this.remotingClient.invokeSync(null, request, timeoutMillis); + assert response != null; + switch (response.getCode()) { + case ResponseCode.SUCCESS_VALUE: { + GetKVConfigResponseHeader responseHeader = + (GetKVConfigResponseHeader) response + .decodeCommandCustomHeader(GetKVConfigResponseHeader.class); + return responseHeader.getValue(); + } + default: + break; + } + + throw new MQClientException(response.getCode(), response.getRemark()); + } + + + /** + * Name Server: 获取指定Namespace下的所有KV + */ + public KVTable getKVListByNamespace(final String namespace, final long timeoutMillis) + throws RemotingException, MQClientException, InterruptedException { + GetKVListByNamespaceRequestHeader requestHeader = new GetKVListByNamespaceRequestHeader(); + requestHeader.setNamespace(namespace); + + RemotingCommand request = + RemotingCommand.createRequestCommand(MQRequestCode.GET_KVLIST_BY_NAMESPACE_VALUE, + requestHeader); + + RemotingCommand response = this.remotingClient.invokeSync(null, request, timeoutMillis); + assert response != null; + switch (response.getCode()) { + case ResponseCode.SUCCESS_VALUE: { + return KVTable.decode(response.getBody(), KVTable.class); + } + default: + break; + } + + throw new MQClientException(response.getCode(), response.getRemark()); + } + + + /** + * Name Server: 删除 value 对应的所有 key + */ + public void deleteKVConfigByValue(final String namespace, final String projectGroup, + final long timeoutMillis) throws RemotingException, MQClientException, InterruptedException { + DeleteKVConfigRequestHeader requestHeader = new DeleteKVConfigRequestHeader(); + requestHeader.setNamespace(namespace); + requestHeader.setKey(projectGroup); + + RemotingCommand request = + RemotingCommand.createRequestCommand(MQRequestCode.DELETE_KV_CONFIG_BY_VALUE_VALUE, + requestHeader); + + RemotingCommand response = this.remotingClient.invokeSync(null, request, timeoutMillis); + assert response != null; + switch (response.getCode()) { + case ResponseCode.SUCCESS_VALUE: { + return; + } + default: + break; + } + + throw new MQClientException(response.getCode(), response.getRemark()); + } + + + /** + * 通知 broker 重置 offset + */ + public Map invokeBrokerToResetOffset(final String addr, final String topic, + final String group, final long timestamp, final boolean isForce, final long timeoutMillis) + throws RemotingException, MQClientException, InterruptedException { + ResetOffsetRequestHeader requestHeader = new ResetOffsetRequestHeader(); + requestHeader.setTopic(topic); + requestHeader.setGroup(group); + requestHeader.setTimestamp(timestamp); + requestHeader.setForce(isForce); + + RemotingCommand request = + RemotingCommand.createRequestCommand(MQRequestCode.INVOKE_BROKER_TO_RESET_OFFSET_VALUE, + requestHeader); + + RemotingCommand response = this.remotingClient.invokeSync(addr, request, timeoutMillis); + assert response != null; + switch (response.getCode()) { + case RemotingProtos.ResponseCode.SUCCESS_VALUE: { + if (response.getBody() != null) { + ResetOffsetBody body = ResetOffsetBody.decode(response.getBody(), ResetOffsetBody.class); + return body.getOffsetTable(); + } + } + default: + break; + } + + throw new MQClientException(response.getCode(), response.getRemark()); + } + + + /** + * 通知 broker 客户端订阅消息处理 + */ + public Map> invokeBrokerToGetConsumerStatus(final String addr, + final String topic, final String group, final String clientAddr, final long timeoutMillis) + throws RemotingException, MQClientException, InterruptedException { + GetConsumerStatusRequestHeader requestHeader = new GetConsumerStatusRequestHeader(); + requestHeader.setTopic(topic); + requestHeader.setGroup(group); + requestHeader.setClientAddr(clientAddr); + + RemotingCommand request = + RemotingCommand.createRequestCommand( + MQRequestCode.INVOKE_BROKER_TO_GET_CONSUMER_STATUS_VALUE, requestHeader); + + RemotingCommand response = this.remotingClient.invokeSync(addr, request, timeoutMillis); + assert response != null; + switch (response.getCode()) { + case RemotingProtos.ResponseCode.SUCCESS_VALUE: { + if (response.getBody() != null) { + GetConsumerStatusBody body = + GetConsumerStatusBody.decode(response.getBody(), GetConsumerStatusBody.class); + return body.getConsumerTable(); + } } default: break; diff --git a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/impl/MQClientManager.java b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/impl/MQClientManager.java index 0c8538c8..3432fd3b 100644 --- a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/impl/MQClientManager.java +++ b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/impl/MQClientManager.java @@ -1,27 +1,38 @@ /** - * $Id: MQClientManager.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.client.impl; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicInteger; -import com.alibaba.rocketmq.client.MQClientConfig; +import com.alibaba.rocketmq.client.ClientConfig; import com.alibaba.rocketmq.client.impl.factory.MQClientFactory; /** - * Client - * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * Client单例管理 * + * @author shijia.wxr + * @since 2013-7-24 */ public class MQClientManager { private static MQClientManager instance = new MQClientManager(); - private AtomicInteger factoryIndexGenerator = new AtomicInteger(); - private ConcurrentHashMap factoryTable = - new ConcurrentHashMap(); + private ConcurrentHashMap factoryTable = + new ConcurrentHashMap(); private MQClientManager() { @@ -34,11 +45,14 @@ public static MQClientManager getInstance() { } - public MQClientFactory getAndCreateMQClientFactory(final MQClientConfig mQClientConfig) { - MQClientFactory factory = this.factoryTable.get(mQClientConfig); + public MQClientFactory getAndCreateMQClientFactory(final ClientConfig clientConfig) { + String clientId = clientConfig.buildMQClientId(); + MQClientFactory factory = this.factoryTable.get(clientId); if (null == factory) { - factory = new MQClientFactory(mQClientConfig, this.factoryIndexGenerator.getAndIncrement()); - MQClientFactory prev = this.factoryTable.putIfAbsent(mQClientConfig, factory); + factory = + new MQClientFactory(clientConfig.cloneClientConfig(), + this.factoryIndexGenerator.getAndIncrement(), clientId); + MQClientFactory prev = this.factoryTable.putIfAbsent(clientId, factory); if (prev != null) { factory = prev; } @@ -49,4 +63,9 @@ public MQClientFactory getAndCreateMQClientFactory(final MQClientConfig mQClient return factory; } + + + public void removeClientFactory(final String clientId) { + this.factoryTable.remove(clientId); + } } diff --git a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/impl/consumer/ConsumeMessageConcurrentlyService.java b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/impl/consumer/ConsumeMessageConcurrentlyService.java new file mode 100644 index 00000000..cf830ac9 --- /dev/null +++ b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/impl/consumer/ConsumeMessageConcurrentlyService.java @@ -0,0 +1,378 @@ +/** + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.rocketmq.client.impl.consumer; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.Executors; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicLong; + +import org.slf4j.Logger; + +import com.alibaba.rocketmq.client.consumer.DefaultMQPushConsumer; +import com.alibaba.rocketmq.client.consumer.listener.ConsumeConcurrentlyContext; +import com.alibaba.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus; +import com.alibaba.rocketmq.client.consumer.listener.MessageListenerConcurrently; +import com.alibaba.rocketmq.client.hook.ConsumeMessageContext; +import com.alibaba.rocketmq.client.log.ClientLogger; +import com.alibaba.rocketmq.client.stat.ConsumerStat; +import com.alibaba.rocketmq.common.MixAll; +import com.alibaba.rocketmq.common.message.MessageConst; +import com.alibaba.rocketmq.common.message.MessageExt; +import com.alibaba.rocketmq.common.message.MessageQueue; +import com.alibaba.rocketmq.remoting.common.RemotingHelper; + + +/** + * 并发消费消息服务 + * + * @author shijia.wxr + * @since 2013-7-24 + */ +public class ConsumeMessageConcurrentlyService implements ConsumeMessageService { + private static final Logger log = ClientLogger.getLog(); + private final DefaultMQPushConsumerImpl defaultMQPushConsumerImpl; + private final DefaultMQPushConsumer defaultMQPushConsumer; + private final MessageListenerConcurrently messageListener; + private final BlockingQueue consumeRequestQueue; + private final ThreadPoolExecutor consumeExecutor; + private final String consumerGroup; + + // 定时线程 + private final ScheduledExecutorService scheduledExecutorService; + + + public ConsumeMessageConcurrentlyService(DefaultMQPushConsumerImpl defaultMQPushConsumerImpl, + MessageListenerConcurrently messageListener) { + this.defaultMQPushConsumerImpl = defaultMQPushConsumerImpl; + this.messageListener = messageListener; + + this.defaultMQPushConsumer = this.defaultMQPushConsumerImpl.getDefaultMQPushConsumer(); + this.consumerGroup = this.defaultMQPushConsumer.getConsumerGroup(); + this.consumeRequestQueue = new LinkedBlockingQueue(); + + this.consumeExecutor = new ThreadPoolExecutor(// + this.defaultMQPushConsumer.getConsumeThreadMin(),// + this.defaultMQPushConsumer.getConsumeThreadMax(),// + 1000 * 60,// + TimeUnit.MILLISECONDS,// + this.consumeRequestQueue,// + new ThreadFactory() { + private AtomicLong threadIndex = new AtomicLong(0); + + + @Override + public Thread newThread(Runnable r) { + return new Thread(r, "ConsumeMessageThread-" // + + ConsumeMessageConcurrentlyService.this.consumerGroup// + + "-" + this.threadIndex.incrementAndGet()); + } + }); + + this.scheduledExecutorService = Executors.newSingleThreadScheduledExecutor(new ThreadFactory() { + @Override + public Thread newThread(Runnable r) { + return new Thread(r, "ConsumeMessageScheduledThread-" + consumerGroup); + } + }); + } + + + public void start() { + } + + + public void shutdown() { + this.scheduledExecutorService.shutdown(); + this.consumeExecutor.shutdown(); + } + + + public ConsumerStat getConsumerStat() { + return this.defaultMQPushConsumerImpl.getConsumerStatManager().getConsumertat(); + } + + class ConsumeRequest implements Runnable { + private final List msgs; + private final ProcessQueue processQueue; + private final MessageQueue messageQueue; + + + public ConsumeRequest(List msgs, ProcessQueue processQueue, MessageQueue messageQueue) { + this.msgs = msgs; + this.processQueue = processQueue; + this.messageQueue = messageQueue; + } + + + private void resetRetryTopic(final List msgs) { + final String groupTopic = MixAll.getRetryTopic(consumerGroup); + for (MessageExt msg : msgs) { + String retryTopic = msg.getProperty(MessageConst.PROPERTY_RETRY_TOPIC); + if (retryTopic != null && groupTopic.equals(msg.getTopic())) { + msg.setTopic(retryTopic); + } + } + } + + + @Override + public void run() { + if (this.processQueue.isDroped()) { + log.info("the message queue not be able to consume, because it's droped {}", + this.messageQueue); + return; + } + + MessageListenerConcurrently listener = ConsumeMessageConcurrentlyService.this.messageListener; + ConsumeConcurrentlyContext context = new ConsumeConcurrentlyContext(messageQueue); + ConsumeConcurrentlyStatus status = null; + + // 执行Hook + ConsumeMessageContext consumeMessageContext = null; + if (ConsumeMessageConcurrentlyService.this.defaultMQPushConsumerImpl.hasHook()) { + consumeMessageContext = new ConsumeMessageContext(); + consumeMessageContext + .setConsumerGroup(ConsumeMessageConcurrentlyService.this.defaultMQPushConsumer + .getConsumerGroup()); + consumeMessageContext.setMq(messageQueue); + consumeMessageContext.setMsgList(msgs); + consumeMessageContext.setSuccess(false); + ConsumeMessageConcurrentlyService.this.defaultMQPushConsumerImpl + .executeHookBefore(consumeMessageContext); + } + + long beginTimestamp = System.currentTimeMillis(); + + try { + this.resetRetryTopic(msgs); + status = listener.consumeMessage(msgs, context); + } + catch (Throwable e) { + log.warn("consumeMessage exception: {} Group: {} Msgs: {} MQ: {}",// + RemotingHelper.exceptionSimpleDesc(e),// + ConsumeMessageConcurrentlyService.this.consumerGroup,// + msgs,// + messageQueue); + } + + long consumeRT = System.currentTimeMillis() - beginTimestamp; + + if (null == status) { + log.warn("consumeMessage return null, Group: {} Msgs: {} MQ: {}",// + ConsumeMessageConcurrentlyService.this.consumerGroup,// + msgs,// + messageQueue); + status = ConsumeConcurrentlyStatus.RECONSUME_LATER; + } + + // 执行Hook + if (ConsumeMessageConcurrentlyService.this.defaultMQPushConsumerImpl.hasHook()) { + consumeMessageContext.setSuccess(ConsumeConcurrentlyStatus.CONSUME_SUCCESS == status); + ConsumeMessageConcurrentlyService.this.defaultMQPushConsumerImpl + .executeHookAfter(consumeMessageContext); + } + + // 记录统计信息 + ConsumeMessageConcurrentlyService.this.getConsumerStat().getConsumeMsgRTTotal() + .addAndGet(consumeRT); + boolean updated = + MixAll.compareAndIncreaseOnly(ConsumeMessageConcurrentlyService.this.getConsumerStat() + .getConsumeMsgRTMax(), consumeRT); + // 耗时最大值新记录 + if (updated) { + log.warn("consumeMessage RT new max: {} Group: {} Msgs: {} MQ: {}",// + consumeRT,// + ConsumeMessageConcurrentlyService.this.consumerGroup,// + msgs,// + messageQueue); + } + + // 如果ProcessQueue是dropped状态,不需要直接更新 offset + if (!processQueue.isDroped()) { + ConsumeMessageConcurrentlyService.this.processConsumeResult(status, context, this); + } + } + + + public List getMsgs() { + return msgs; + } + + + public ProcessQueue getProcessQueue() { + return processQueue; + } + + + public MessageQueue getMessageQueue() { + return messageQueue; + } + } + + + public boolean sendMessageBack(final MessageExt msg, final ConsumeConcurrentlyContext context) { + // 如果用户没有设置,服务器会根据重试次数自动叠加延时时间 + int delayLevel = context.getDelayLevelWhenNextConsume(); + + try { + this.defaultMQPushConsumerImpl.sendMessageBack(msg, delayLevel); + return true; + } + catch (Exception e) { + log.error("sendMessageBack exception, group: " + this.consumerGroup + " msg: " + msg.toString(), + e); + } + + return false; + } + + + public void processConsumeResult(// + final ConsumeConcurrentlyStatus status, // + final ConsumeConcurrentlyContext context, // + final ConsumeRequest consumeRequest// + ) { + int ackIndex = context.getAckIndex(); + + if (consumeRequest.getMsgs().isEmpty()) + return; + + switch (status) { + case CONSUME_SUCCESS: + if (ackIndex >= consumeRequest.getMsgs().size()) { + ackIndex = consumeRequest.getMsgs().size() - 1; + } + int ok = ackIndex + 1; + int failed = consumeRequest.getMsgs().size() - ok; + // 统计信息 + this.getConsumerStat().getConsumeMsgOKTotal().addAndGet(ok); + this.getConsumerStat().getConsumeMsgFailedTotal().addAndGet(failed); + break; + case RECONSUME_LATER: + ackIndex = -1; + // 统计信息 + this.getConsumerStat().getConsumeMsgFailedTotal().addAndGet(consumeRequest.getMsgs().size()); + break; + default: + break; + } + + switch (this.defaultMQPushConsumer.getMessageModel()) { + case BROADCASTING: + // 如果是广播模式,直接丢弃失败消息,需要在文档中告知用户 + // 这样做的原因:广播模式对于失败重试代价过高,对整个集群性能会有较大影响,失败重试功能交由应用处理 + for (int i = ackIndex + 1; i < consumeRequest.getMsgs().size(); i++) { + MessageExt msg = consumeRequest.getMsgs().get(i); + log.warn("BROADCASTING, the message consume failed, drop it, {}", msg.toString()); + } + break; + case CLUSTERING: + // 处理消费失败的消息,直接发回到Broker + List msgBackFailed = new ArrayList(consumeRequest.getMsgs().size()); + for (int i = ackIndex + 1; i < consumeRequest.getMsgs().size(); i++) { + MessageExt msg = consumeRequest.getMsgs().get(i); + boolean result = this.sendMessageBack(msg, context); + if (!result) { + msg.setReconsumeTimes(msg.getReconsumeTimes() + 1); + msgBackFailed.add(msg); + } + } + + if (!msgBackFailed.isEmpty()) { + // 发回失败的消息仍然要保留 + consumeRequest.getMsgs().removeAll(msgBackFailed); + + // 此过程处理失败的消息,需要在Client中做定时消费,直到成功 + this.submitConsumeRequestLater(msgBackFailed, consumeRequest.getProcessQueue(), + consumeRequest.getMessageQueue()); + } + break; + default: + break; + } + + long offset = consumeRequest.getProcessQueue().removeMessage(consumeRequest.getMsgs()); + if (offset >= 0) { + this.defaultMQPushConsumerImpl.getOffsetStore().updateOffset(consumeRequest.getMessageQueue(), + offset, true); + } + } + + + /** + * 在Consumer本地定时线程中定时重试 + */ + private void submitConsumeRequestLater(// + final List msgs, // + final ProcessQueue processQueue, // + final MessageQueue messageQueue// + ) { + + this.scheduledExecutorService.schedule(new Runnable() { + + @Override + public void run() { + ConsumeMessageConcurrentlyService.this.submitConsumeRequest(msgs, processQueue, messageQueue, + true); + } + }, 5000, TimeUnit.MILLISECONDS); + } + + + @Override + public void submitConsumeRequest(// + final List msgs, // + final ProcessQueue processQueue, // + final MessageQueue messageQueue, // + final boolean dispathToConsume) { + final int consumeBatchSize = this.defaultMQPushConsumer.getConsumeMessageBatchMaxSize(); + if (msgs.size() <= consumeBatchSize) { + ConsumeRequest consumeRequest = new ConsumeRequest(msgs, processQueue, messageQueue); + this.consumeExecutor.submit(consumeRequest); + } + else { + for (int total = 0; total < msgs.size();) { + List msgThis = new ArrayList(consumeBatchSize); + for (int i = 0; i < consumeBatchSize; i++, total++) { + if (total < msgs.size()) { + msgThis.add(msgs.get(total)); + } + else { + break; + } + } + + ConsumeRequest consumeRequest = new ConsumeRequest(msgThis, processQueue, messageQueue); + this.consumeExecutor.submit(consumeRequest); + } + } + } + + + @Override + public void updateCorePoolSize(int corePoolSize) { + if (corePoolSize > 0 && corePoolSize <= Short.MAX_VALUE) { + this.consumeExecutor.setCorePoolSize(corePoolSize); + } + } +} diff --git a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/impl/consumer/ConsumeMessageOrderlyService.java b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/impl/consumer/ConsumeMessageOrderlyService.java new file mode 100644 index 00000000..880d0de4 --- /dev/null +++ b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/impl/consumer/ConsumeMessageOrderlyService.java @@ -0,0 +1,451 @@ +/** + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.rocketmq.client.impl.consumer; + +import java.util.List; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.Executors; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicLong; + +import org.slf4j.Logger; + +import com.alibaba.rocketmq.client.consumer.DefaultMQPushConsumer; +import com.alibaba.rocketmq.client.consumer.listener.ConsumeOrderlyContext; +import com.alibaba.rocketmq.client.consumer.listener.ConsumeOrderlyStatus; +import com.alibaba.rocketmq.client.consumer.listener.MessageListenerOrderly; +import com.alibaba.rocketmq.client.hook.ConsumeMessageContext; +import com.alibaba.rocketmq.client.log.ClientLogger; +import com.alibaba.rocketmq.client.stat.ConsumerStat; +import com.alibaba.rocketmq.common.MixAll; +import com.alibaba.rocketmq.common.message.MessageExt; +import com.alibaba.rocketmq.common.message.MessageQueue; +import com.alibaba.rocketmq.common.protocol.heartbeat.MessageModel; +import com.alibaba.rocketmq.remoting.common.RemotingHelper; + + +/** + * 顺序消费消息服务 + * + * @author shijia.wxr + * @since 2013-6-27 + */ +public class ConsumeMessageOrderlyService implements ConsumeMessageService { + private static final Logger log = ClientLogger.getLog(); + private final static long MaxTimeConsumeContinuously = Long.parseLong(System.getProperty( + "rocketmq.client.maxTimeConsumeContinuously", "60000")); + + private volatile boolean stoped = false; + + private final DefaultMQPushConsumerImpl defaultMQPushConsumerImpl; + private final DefaultMQPushConsumer defaultMQPushConsumer; + private final MessageListenerOrderly messageListener; + private final BlockingQueue consumeRequestQueue; + private final ThreadPoolExecutor consumeExecutor; + private final String consumerGroup; + private final MessageQueueLock messageQueueLock = new MessageQueueLock(); + + // 定时线程 + private final ScheduledExecutorService scheduledExecutorService; + + + public ConsumeMessageOrderlyService(DefaultMQPushConsumerImpl defaultMQPushConsumerImpl, + MessageListenerOrderly messageListener) { + this.defaultMQPushConsumerImpl = defaultMQPushConsumerImpl; + this.messageListener = messageListener; + + this.defaultMQPushConsumer = this.defaultMQPushConsumerImpl.getDefaultMQPushConsumer(); + this.consumerGroup = this.defaultMQPushConsumer.getConsumerGroup(); + this.consumeRequestQueue = new LinkedBlockingQueue(); + + this.consumeExecutor = new ThreadPoolExecutor(// + this.defaultMQPushConsumer.getConsumeThreadMin(),// + this.defaultMQPushConsumer.getConsumeThreadMax(),// + 1000 * 60,// + TimeUnit.MILLISECONDS,// + this.consumeRequestQueue,// + new ThreadFactory() { + private AtomicLong threadIndex = new AtomicLong(0); + + + @Override + public Thread newThread(Runnable r) { + return new Thread(r, "ConsumeMessageThread-" // + + ConsumeMessageOrderlyService.this.consumerGroup// + + "-" + this.threadIndex.incrementAndGet()); + } + }); + + this.scheduledExecutorService = Executors.newSingleThreadScheduledExecutor(new ThreadFactory() { + @Override + public Thread newThread(Runnable r) { + return new Thread(r, "ConsumeMessageScheduledThread-" + consumerGroup); + } + }); + } + + + public void start() { + // 启动定时lock队列服务 + if (MessageModel.CLUSTERING.equals(ConsumeMessageOrderlyService.this.defaultMQPushConsumerImpl + .messageModel())) { + this.scheduledExecutorService.scheduleAtFixedRate(new Runnable() { + @Override + public void run() { + ConsumeMessageOrderlyService.this.lockMQPeriodically(); + } + }, 1000 * 1, ProcessQueue.RebalanceLockInterval, TimeUnit.MILLISECONDS); + } + } + + + public void shutdown() { + this.stoped = true; + this.scheduledExecutorService.shutdown(); + this.consumeExecutor.shutdown(); + if (MessageModel.CLUSTERING.equals(this.defaultMQPushConsumerImpl.messageModel())) { + this.unlockAllMQ(); + } + } + + + public synchronized void unlockAllMQ() { + this.defaultMQPushConsumerImpl.getRebalanceImpl().unlockAll(false); + } + + + public synchronized void lockMQPeriodically() { + if (!this.stoped) { + this.defaultMQPushConsumerImpl.getRebalanceImpl().lockAll(); + } + } + + + public synchronized boolean lockOneMQ(final MessageQueue mq) { + if (!this.stoped) { + return this.defaultMQPushConsumerImpl.getRebalanceImpl().lock(mq); + } + + return false; + } + + + public void tryLockLaterAndReconsume(final MessageQueue mq, final ProcessQueue processQueue, + final long delayMills) { + this.scheduledExecutorService.schedule(new Runnable() { + @Override + public void run() { + boolean lockOK = ConsumeMessageOrderlyService.this.lockOneMQ(mq); + if (lockOK) { + ConsumeMessageOrderlyService.this.submitConsumeRequestLater(processQueue, mq, 10); + } + else { + ConsumeMessageOrderlyService.this.submitConsumeRequestLater(processQueue, mq, 3000); + } + } + }, delayMills, TimeUnit.MILLISECONDS); + } + + + public ConsumerStat getConsumerStat() { + return this.defaultMQPushConsumerImpl.getConsumerStatManager().getConsumertat(); + } + + class ConsumeRequest implements Runnable { + private final ProcessQueue processQueue; + private final MessageQueue messageQueue; + + + public ConsumeRequest(ProcessQueue processQueue, MessageQueue messageQueue) { + this.processQueue = processQueue; + this.messageQueue = messageQueue; + } + + + @Override + public void run() { + // 保证在当前Consumer内,同一队列串行消费 + final Object objLock = messageQueueLock.fetchLockObject(this.messageQueue); + synchronized (objLock) { + // 保证在Consumer集群,同一队列串行消费 + if (MessageModel.BROADCASTING + .equals(ConsumeMessageOrderlyService.this.defaultMQPushConsumerImpl.messageModel()) + || this.processQueue.isLocked() || !this.processQueue.isLockExpired()) { + final long beginTime = System.currentTimeMillis(); + for (boolean continueConsume = true; continueConsume;) { + if (this.processQueue.isDroped()) { + log.warn("the message queue not be able to consume, because it's dropped. {}", + this.messageQueue); + break; + } + + if (MessageModel.CLUSTERING + .equals(ConsumeMessageOrderlyService.this.defaultMQPushConsumerImpl + .messageModel()) + && !this.processQueue.isLocked()) { + log.warn("the message queue not locked, so consume later, {}", this.messageQueue); + ConsumeMessageOrderlyService.this.tryLockLaterAndReconsume(this.messageQueue, + this.processQueue, 10); + break; + } + + if (MessageModel.CLUSTERING + .equals(ConsumeMessageOrderlyService.this.defaultMQPushConsumerImpl + .messageModel()) + && this.processQueue.isLockExpired()) { + log.warn("the message queue lock expired, so consume later, {}", + this.messageQueue); + ConsumeMessageOrderlyService.this.tryLockLaterAndReconsume(this.messageQueue, + this.processQueue, 10); + break; + } + + // 在线程数小于队列数情况下,防止个别队列被饿死 + long interval = System.currentTimeMillis() - beginTime; + if (interval > MaxTimeConsumeContinuously) { + // 过10ms后再消费 + ConsumeMessageOrderlyService.this.submitConsumeRequestLater(processQueue, + messageQueue, 10); + break; + } + + final int consumeBatchSize = + ConsumeMessageOrderlyService.this.defaultMQPushConsumer + .getConsumeMessageBatchMaxSize(); + + List msgs = this.processQueue.takeMessags(consumeBatchSize); + if (!msgs.isEmpty()) { + final ConsumeOrderlyContext context = + new ConsumeOrderlyContext(this.messageQueue); + + ConsumeOrderlyStatus status = null; + + // 执行Hook + ConsumeMessageContext consumeMessageContext = null; + if (ConsumeMessageOrderlyService.this.defaultMQPushConsumerImpl.hasHook()) { + consumeMessageContext = new ConsumeMessageContext(); + consumeMessageContext + .setConsumerGroup(ConsumeMessageOrderlyService.this.defaultMQPushConsumer + .getConsumerGroup()); + consumeMessageContext.setMq(messageQueue); + consumeMessageContext.setMsgList(msgs); + consumeMessageContext.setSuccess(false); + ConsumeMessageOrderlyService.this.defaultMQPushConsumerImpl + .executeHookBefore(consumeMessageContext); + } + + long beginTimestamp = System.currentTimeMillis(); + + try { + status = messageListener.consumeMessage(msgs, context); + } + catch (Throwable e) { + log.warn("consumeMessage exception: {} Group: {} Msgs: {} MQ: {}",// + RemotingHelper.exceptionSimpleDesc(e),// + ConsumeMessageOrderlyService.this.consumerGroup,// + msgs,// + messageQueue); + } + + long consumeRT = System.currentTimeMillis() - beginTimestamp; + + // 用户抛出异常或者返回null,都挂起队列 + if (null == status) { + status = ConsumeOrderlyStatus.SUSPEND_CURRENT_QUEUE_A_MOMENT; + } + + // 执行Hook + if (ConsumeMessageOrderlyService.this.defaultMQPushConsumerImpl.hasHook()) { + consumeMessageContext.setSuccess(ConsumeOrderlyStatus.SUCCESS == status + || ConsumeOrderlyStatus.COMMIT == status); + ConsumeMessageOrderlyService.this.defaultMQPushConsumerImpl + .executeHookAfter(consumeMessageContext); + } + + // 记录统计信息 + ConsumeMessageOrderlyService.this.getConsumerStat().getConsumeMsgRTTotal() + .addAndGet(consumeRT); + MixAll.compareAndIncreaseOnly(ConsumeMessageOrderlyService.this.getConsumerStat() + .getConsumeMsgRTMax(), consumeRT); + + continueConsume = + ConsumeMessageOrderlyService.this.processConsumeResult(msgs, status, + context, this); + } + else { + continueConsume = false; + } + } + } + // 没有拿到当前队列的锁,稍后再消费 + else { + if (this.processQueue.isDroped()) { + log.warn("the message queue not be able to consume, because it's dropped. {}", + this.messageQueue); + return; + } + ConsumeMessageOrderlyService.this.tryLockLaterAndReconsume(this.messageQueue, + this.processQueue, 10); + } + } + } + + + public ProcessQueue getProcessQueue() { + return processQueue; + } + + + public MessageQueue getMessageQueue() { + return messageQueue; + } + } + + + public boolean processConsumeResult(// + final List msgs, // + final ConsumeOrderlyStatus status, // + final ConsumeOrderlyContext context, // + final ConsumeRequest consumeRequest// + ) { + boolean continueConsume = true; + long commitOffset = -1L; + // 非事务方式,自动提交 + if (context.isAutoCommit()) { + switch (status) { + case COMMIT: + case ROLLBACK: + log.warn( + "the message queue consume result is illegal, we think you want to ack these message {}", + consumeRequest.getMessageQueue()); + case SUCCESS: + commitOffset = consumeRequest.getProcessQueue().commit(); + // 统计信息 + this.getConsumerStat().getConsumeMsgOKTotal().addAndGet(msgs.size()); + break; + case SUSPEND_CURRENT_QUEUE_A_MOMENT: + consumeRequest.getProcessQueue().makeMessageToCosumeAgain(msgs); + this.submitConsumeRequestLater(// + consumeRequest.getProcessQueue(), // + consumeRequest.getMessageQueue(), // + context.getSuspendCurrentQueueTimeMillis()); + continueConsume = false; + + // 统计信息 + this.getConsumerStat().getConsumeMsgFailedTotal().addAndGet(msgs.size()); + break; + default: + break; + } + } + // 事务方式,由用户来控制提交回滚 + else { + switch (status) { + case SUCCESS: + // 统计信息 + this.getConsumerStat().getConsumeMsgOKTotal().addAndGet(msgs.size()); + break; + case COMMIT: + commitOffset = consumeRequest.getProcessQueue().commit(); + // 统计信息 + this.getConsumerStat().getConsumeMsgOKTotal().addAndGet(msgs.size()); + break; + case ROLLBACK: + // 如果Rollback后,最好suspend一会儿再消费,防止应用无限Rollback下去 + consumeRequest.getProcessQueue().rollback(); + this.submitConsumeRequestLater(// + consumeRequest.getProcessQueue(), // + consumeRequest.getMessageQueue(), // + context.getSuspendCurrentQueueTimeMillis()); + continueConsume = false; + // 统计信息 + this.getConsumerStat().getConsumeMsgFailedTotal().addAndGet(msgs.size()); + break; + case SUSPEND_CURRENT_QUEUE_A_MOMENT: + consumeRequest.getProcessQueue().makeMessageToCosumeAgain(msgs); + this.submitConsumeRequestLater(// + consumeRequest.getProcessQueue(), // + consumeRequest.getMessageQueue(), // + context.getSuspendCurrentQueueTimeMillis()); + continueConsume = false; + // 统计信息 + this.getConsumerStat().getConsumeMsgFailedTotal().addAndGet(msgs.size()); + break; + default: + break; + } + } + + if (commitOffset >= 0) { + this.defaultMQPushConsumerImpl.getOffsetStore().updateOffset(consumeRequest.getMessageQueue(), + commitOffset, false); + } + + return continueConsume; + } + + + /** + * 在Consumer本地定时线程中定时重试 + */ + private void submitConsumeRequestLater(// + final ProcessQueue processQueue, // + final MessageQueue messageQueue,// + final long suspendTimeMillis// + ) { + long timeMillis = suspendTimeMillis; + if (timeMillis < 10) { + timeMillis = 10; + } + else if (timeMillis > 30000) { + timeMillis = 30000; + } + + this.scheduledExecutorService.schedule(new Runnable() { + + @Override + public void run() { + ConsumeMessageOrderlyService.this + .submitConsumeRequest(null, processQueue, messageQueue, true); + } + }, timeMillis, TimeUnit.MILLISECONDS); + } + + + @Override + public void submitConsumeRequest(// + final List msgs, // + final ProcessQueue processQueue, // + final MessageQueue messageQueue, // + final boolean dispathToConsume) { + if (dispathToConsume) { + ConsumeRequest consumeRequest = new ConsumeRequest(processQueue, messageQueue); + this.consumeExecutor.submit(consumeRequest); + } + } + + + @Override + public void updateCorePoolSize(int corePoolSize) { + if (corePoolSize > 0 && corePoolSize <= Short.MAX_VALUE) { + this.consumeExecutor.setCorePoolSize(corePoolSize); + } + } +} diff --git a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/impl/consumer/ConsumeMessageService.java b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/impl/consumer/ConsumeMessageService.java new file mode 100644 index 00000000..ac1f0e06 --- /dev/null +++ b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/impl/consumer/ConsumeMessageService.java @@ -0,0 +1,45 @@ +/** + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.rocketmq.client.impl.consumer; + +import java.util.List; + +import com.alibaba.rocketmq.common.message.MessageExt; +import com.alibaba.rocketmq.common.message.MessageQueue; + + +/** + * 消费消息服务,公共接口 + * + * @author shijia.wxr + * @since 2013-7-24 + */ +public interface ConsumeMessageService { + public void start(); + + + public void shutdown(); + + + public void updateCorePoolSize(int corePoolSize); + + + public void submitConsumeRequest(// + final List msgs, // + final ProcessQueue processQueue, // + final MessageQueue messageQueue, // + final boolean dispathToConsume); +} diff --git a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/impl/consumer/DefaultMQPullConsumerImpl.java b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/impl/consumer/DefaultMQPullConsumerImpl.java index b4f37b7f..d6ff8e3c 100644 --- a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/impl/consumer/DefaultMQPullConsumerImpl.java +++ b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/impl/consumer/DefaultMQPullConsumerImpl.java @@ -1,31 +1,52 @@ /** - * $Id: DefaultMQPullConsumerImpl.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.client.impl.consumer; -import java.nio.ByteBuffer; import java.util.HashSet; import java.util.List; +import java.util.Map; import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; + +import org.slf4j.Logger; import com.alibaba.rocketmq.client.QueryResult; +import com.alibaba.rocketmq.client.Validators; import com.alibaba.rocketmq.client.consumer.DefaultMQPullConsumer; import com.alibaba.rocketmq.client.consumer.PullCallback; import com.alibaba.rocketmq.client.consumer.PullResult; -import com.alibaba.rocketmq.client.consumer.PullStatus; +import com.alibaba.rocketmq.client.consumer.store.LocalFileOffsetStore; +import com.alibaba.rocketmq.client.consumer.store.OffsetStore; +import com.alibaba.rocketmq.client.consumer.store.ReadOffsetType; +import com.alibaba.rocketmq.client.consumer.store.RemoteBrokerOffsetStore; import com.alibaba.rocketmq.client.exception.MQBrokerException; import com.alibaba.rocketmq.client.exception.MQClientException; import com.alibaba.rocketmq.client.impl.CommunicationMode; -import com.alibaba.rocketmq.client.impl.FindBrokerResult; import com.alibaba.rocketmq.client.impl.MQClientManager; import com.alibaba.rocketmq.client.impl.factory.MQClientFactory; -import com.alibaba.rocketmq.common.MessageDecoder; -import com.alibaba.rocketmq.common.MessageExt; -import com.alibaba.rocketmq.common.MessageQueue; +import com.alibaba.rocketmq.client.log.ClientLogger; +import com.alibaba.rocketmq.common.MixAll; import com.alibaba.rocketmq.common.ServiceState; -import com.alibaba.rocketmq.common.TopicFilterType; -import com.alibaba.rocketmq.common.protocol.header.QueryConsumerOffsetRequestHeader; -import com.alibaba.rocketmq.common.protocol.header.UpdateConsumerOffsetRequestHeader; +import com.alibaba.rocketmq.common.consumer.ConsumeFromWhere; +import com.alibaba.rocketmq.common.filter.FilterAPI; +import com.alibaba.rocketmq.common.help.FAQUrl; +import com.alibaba.rocketmq.common.message.Message; +import com.alibaba.rocketmq.common.message.MessageConst; +import com.alibaba.rocketmq.common.message.MessageExt; +import com.alibaba.rocketmq.common.message.MessageQueue; import com.alibaba.rocketmq.common.protocol.heartbeat.ConsumeType; import com.alibaba.rocketmq.common.protocol.heartbeat.MessageModel; import com.alibaba.rocketmq.common.protocol.heartbeat.SubscriptionData; @@ -34,15 +55,21 @@ /** - * Consumerʵ + * Pull方式的Consumer实现 * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * @author shijia.wxr + * @since 2013-7-24 */ public class DefaultMQPullConsumerImpl implements MQConsumerInner { - private ServiceState serviceState = ServiceState.CREATE_JUST; + private final Logger log = ClientLogger.getLog(); private final DefaultMQPullConsumer defaultMQPullConsumer; + private ServiceState serviceState = ServiceState.CREATE_JUST; private MQClientFactory mQClientFactory; private PullAPIWrapper pullAPIWrapper; + // 消费进度存储 + private OffsetStore offsetStore; + // Rebalance实现 + private RebalanceImpl rebalanceImpl = new RebalancePullImpl(this); public DefaultMQPullConsumerImpl(final DefaultMQPullConsumer defaultMQPullConsumer) { @@ -50,68 +77,43 @@ public DefaultMQPullConsumerImpl(final DefaultMQPullConsumer defaultMQPullConsum } - public void start() throws MQClientException { - switch (this.serviceState) { - case CREATE_JUST: - this.serviceState = ServiceState.RUNNING; - - this.mQClientFactory = - MQClientManager.getInstance().getAndCreateMQClientFactory( - this.defaultMQPullConsumer.getMQClientConfig()); + public void createTopic(String key, String newTopic, int queueNum) throws MQClientException { + this.makeSureStateOK(); + this.mQClientFactory.getMQAdminImpl().createTopic(key, newTopic, queueNum); + } - this.pullAPIWrapper = new PullAPIWrapper(// - mQClientFactory,// - this.defaultMQPullConsumer.getConsumerGroup(),// - this.defaultMQPullConsumer.getConsumeFromWhichNode()); - boolean registerOK = - mQClientFactory.registerConsumer(this.defaultMQPullConsumer.getConsumerGroup(), this); - if (!registerOK) { - this.serviceState = ServiceState.CREATE_JUST; - throw new MQClientException("The consumer group[" + this.defaultMQPullConsumer.getConsumerGroup() - + "] has created already, specifed another name please.", null); - } - - mQClientFactory.start(); - break; - case RUNNING: - break; - case SHUTDOWN_ALREADY: - break; - default: - break; + private void makeSureStateOK() throws MQClientException { + if (this.serviceState != ServiceState.RUNNING) { + throw new MQClientException("The consumer service state not OK, "// + + this.serviceState// + + FAQUrl.suggestTodo(FAQUrl.CLIENT_SERVICE_NOT_OK), null); } } - public void shutdown() { - switch (this.serviceState) { - case CREATE_JUST: - break; - case RUNNING: - this.serviceState = ServiceState.SHUTDOWN_ALREADY; - this.mQClientFactory.unregisterConsumer(this.defaultMQPullConsumer.getConsumerGroup()); - this.mQClientFactory.shutdown(); - break; - case SHUTDOWN_ALREADY: - break; - default: - break; - } + public long fetchConsumeOffset(MessageQueue mq, boolean fromStore) throws MQClientException { + this.makeSureStateOK(); + return this.offsetStore.readOffset(mq, fromStore ? ReadOffsetType.READ_FROM_STORE + : ReadOffsetType.MEMORY_FIRST_THEN_STORE); } - private void makeSureStateOK() throws MQClientException { - if (this.serviceState != ServiceState.RUNNING) { - throw new MQClientException("The producer service state not OK", null); + public Set fetchMessageQueuesInBalance(String topic) throws MQClientException { + this.makeSureStateOK(); + if (null == topic) { + throw new IllegalArgumentException("topic is null"); } - } + ConcurrentHashMap mqTable = this.rebalanceImpl.getProcessQueueTable(); + Set mqResult = new HashSet(); + for (MessageQueue mq : mqTable.keySet()) { + if (mq.getTopic().equals(topic)) { + mqResult.add(mq); + } + } - public void createTopic(String key, String newTopic, int queueNum, TopicFilterType topicFilterType, - boolean order) throws MQClientException { - this.makeSureStateOK(); - this.mQClientFactory.getMQAdminImpl().createTopic(key, newTopic, queueNum, topicFilterType, order); + return mqResult; } @@ -121,46 +123,132 @@ public List fetchPublishMessageQueues(String topic) throws MQClien } - public long searchOffset(MessageQueue mq, long timestamp) throws MQClientException { + public Set fetchSubscribeMessageQueues(String topic) throws MQClientException { this.makeSureStateOK(); - return this.mQClientFactory.getMQAdminImpl().searchOffset(mq, timestamp); + return this.mQClientFactory.getMQAdminImpl().fetchSubscribeMessageQueues(topic); } - public long getMaxOffset(MessageQueue mq) throws MQClientException { + public long earliestMsgStoreTime(MessageQueue mq) throws MQClientException { this.makeSureStateOK(); - return this.mQClientFactory.getMQAdminImpl().getMaxOffset(mq); + return this.mQClientFactory.getMQAdminImpl().earliestMsgStoreTime(mq); } - public long getMinOffset(MessageQueue mq) throws MQClientException { - this.makeSureStateOK(); - return this.mQClientFactory.getMQAdminImpl().getMinOffset(mq); + @Override + public String groupName() { + return this.defaultMQPullConsumer.getConsumerGroup(); } - public long getEarliestMsgStoreTime(MessageQueue mq) throws MQClientException { - this.makeSureStateOK(); - return this.mQClientFactory.getMQAdminImpl().getEarliestMsgStoreTime(mq); + @Override + public MessageModel messageModel() { + return this.defaultMQPullConsumer.getMessageModel(); + } + + + @Override + public ConsumeType consumeType() { + return ConsumeType.CONSUME_ACTIVELY; + } + + + @Override + public ConsumeFromWhere consumeFromWhere() { + return ConsumeFromWhere.CONSUME_FROM_LAST_OFFSET; } - public MessageExt viewMessage(String msgId) throws RemotingException, MQBrokerException, InterruptedException, - MQClientException { + @Override + public Set subscriptions() { + Set result = new HashSet(); + + Set topics = this.defaultMQPullConsumer.getRegisterTopics(); + if (topics != null) { + synchronized (topics) { + for (String t : topics) { + SubscriptionData ms = new SubscriptionData(t, SubscriptionData.SUB_ALL); + ms.setSubVersion(0L); + result.add(ms); + } + } + } + + return result; + } + + + @Override + public void doRebalance() { + if (this.rebalanceImpl != null) { + this.rebalanceImpl.doRebalance(); + } + } + + + @Override + public void persistConsumerOffset() { + try { + this.makeSureStateOK(); + Set mqs = new HashSet(); + Set allocateMq = this.rebalanceImpl.getProcessQueueTable().keySet(); + if (allocateMq != null) { + mqs.addAll(allocateMq); + } + this.offsetStore.persistAll(mqs); + } + catch (Exception e) { + log.error("group: " + this.defaultMQPullConsumer.getConsumerGroup() + + " persistConsumerOffset exception", e); + } + } + + + @Override + public void updateTopicSubscribeInfo(String topic, Set info) { + Map subTable = this.rebalanceImpl.getSubscriptionInner(); + if (subTable != null) { + if (subTable.containsKey(topic)) { + this.rebalanceImpl.getTopicSubscribeInfoTable().put(topic, info); + } + } + } + + + @Override + public boolean isSubscribeTopicNeedUpdate(String topic) { + Map subTable = this.rebalanceImpl.getSubscriptionInner(); + if (subTable != null) { + if (subTable.containsKey(topic)) { + return !this.rebalanceImpl.topicSubscribeInfoTable.containsKey(topic); + } + } + + return false; + } + + + public long maxOffset(MessageQueue mq) throws MQClientException { this.makeSureStateOK(); - return this.mQClientFactory.getMQAdminImpl().viewMessage(msgId); + return this.mQClientFactory.getMQAdminImpl().maxOffset(mq); } - public QueryResult queryMessage(String topic, String key, int maxNum, long begin, long end) - throws MQClientException, InterruptedException { + public long minOffset(MessageQueue mq) throws MQClientException { this.makeSureStateOK(); - return this.mQClientFactory.getMQAdminImpl().queryMessage(topic, key, maxNum, begin, end); + return this.mQClientFactory.getMQAdminImpl().minOffset(mq); } - private PullResult pullSyncImpl(MessageQueue mq, String subExpression, long offset, int maxNums, boolean block) + public PullResult pull(MessageQueue mq, String subExpression, long offset, int maxNums) throws MQClientException, RemotingException, MQBrokerException, InterruptedException { + return this.pullSyncImpl(mq, subExpression, offset, maxNums, false); + } + + + private PullResult pullSyncImpl(MessageQueue mq, String subExpression, long offset, int maxNums, + boolean block) throws MQClientException, RemotingException, MQBrokerException, + InterruptedException { this.makeSureStateOK(); if (null == mq) { @@ -175,40 +263,57 @@ private PullResult pullSyncImpl(MessageQueue mq, String subExpression, long offs throw new MQClientException("maxNums <= 0", null); } + // 自动订阅 + this.subscriptionAutomatically(mq.getTopic()); + int sysFlag = PullSysFlag.buildSysFlag(false, block, true); - String subExpressionInner = subExpression != null ? subExpression : SubscriptionData.SUB_ALL; + SubscriptionData subscriptionData; + try { + subscriptionData = FilterAPI.buildSubscriptionData(mq.getTopic(), subExpression); + } + catch (Exception e) { + throw new MQClientException("parse subscription error", e); + } long timeoutMillis = block ? this.defaultMQPullConsumer.getConsumerTimeoutMillisWhenSuspend() : this.defaultMQPullConsumer.getConsumerPullTimeoutMillis(); - PullResult pullResult = - this.pullAPIWrapper.pullKernelImpl(mq, subExpressionInner, offset, maxNums, sysFlag, 0, - this.defaultMQPullConsumer.getBrokerSuspendMaxTimeMillis(), timeoutMillis, - CommunicationMode.SYNC, null); - - return this.processPullResult(mq, pullResult); + PullResult pullResult = this.pullAPIWrapper.pullKernelImpl(// + mq, // 1 + subscriptionData.getSubString(), // 2 + 0L, // 3 + offset, // 4 + maxNums, // 5 + sysFlag, // 6 + 0, // 7 + this.defaultMQPullConsumer.getBrokerSuspendMaxTimeMillis(), // 8 + timeoutMillis, // 9 + CommunicationMode.SYNC, // 10 + null// 11 + ); + + return this.pullAPIWrapper.processPullResult(mq, pullResult, subscriptionData); } - /** - * ȡдҪϢл - */ - private PullResult processPullResult(final MessageQueue mq, final PullResult pullResult) { - PullResultExt pullResultExt = (PullResultExt) pullResult; - - this.pullAPIWrapper.updatePullFromWhichNode(mq, pullResultExt.isSuggestPullingFromSlave()); - if (PullStatus.FOUND == pullResult.getPullStatus()) { - ByteBuffer byteBuffer = ByteBuffer.wrap(pullResultExt.getMessageBinary()); - List msgList = MessageDecoder.decodes(byteBuffer); - pullResultExt.setMsgFoundList(msgList); + private void subscriptionAutomatically(final String topic) { + if (!this.rebalanceImpl.getSubscriptionInner().containsKey(topic)) { + try { + SubscriptionData subscriptionData = + FilterAPI.buildSubscriptionData(topic, SubscriptionData.SUB_ALL); + this.rebalanceImpl.subscriptionInner.putIfAbsent(topic, subscriptionData); + } + catch (Exception e) { + } } + } - // GCͷڴ - pullResultExt.setMessageBinary(null); - return pullResult; + public void pull(MessageQueue mq, String subExpression, long offset, int maxNums, + PullCallback pullCallback) throws MQClientException, RemotingException, InterruptedException { + this.pullAsyncImpl(mq, subExpression, offset, maxNums, pullCallback, false); } @@ -238,29 +343,47 @@ private void pullAsyncImpl(// throw new MQClientException("pullCallback is null", null); } - try { + // 自动订阅 + this.subscriptionAutomatically(mq.getTopic()); + try { int sysFlag = PullSysFlag.buildSysFlag(false, block, true); - String subExpressionInner = subExpression != null ? subExpression : SubscriptionData.SUB_ALL; + final SubscriptionData subscriptionData; + try { + subscriptionData = FilterAPI.buildSubscriptionData(mq.getTopic(), subExpression); + } + catch (Exception e) { + throw new MQClientException("parse subscription error", e); + } long timeoutMillis = block ? this.defaultMQPullConsumer.getConsumerTimeoutMillisWhenSuspend() : this.defaultMQPullConsumer.getConsumerPullTimeoutMillis(); - this.pullAPIWrapper.pullKernelImpl(mq, subExpressionInner, offset, maxNums, sysFlag, 0, - this.defaultMQPullConsumer.getBrokerSuspendMaxTimeMillis(), timeoutMillis, - CommunicationMode.ASYNC, new PullCallback() { + this.pullAPIWrapper.pullKernelImpl(// + mq, // 1 + subscriptionData.getSubString(), // 2 + 0L, // 3 + offset, // 4 + maxNums, // 5 + sysFlag, // 6 + 0, // 7 + this.defaultMQPullConsumer.getBrokerSuspendMaxTimeMillis(), // 8 + timeoutMillis, // 9 + CommunicationMode.ASYNC, // 10 + new PullCallback() { @Override - public void onSuccess(PullResult pullResult) { - pullCallback.onSuccess(DefaultMQPullConsumerImpl.this.processPullResult(mq, pullResult)); + public void onException(Throwable e) { + pullCallback.onException(e); } @Override - public void onException(Throwable e) { - pullCallback.onException(e); + public void onSuccess(PullResult pullResult) { + pullCallback.onSuccess(DefaultMQPullConsumerImpl.this.pullAPIWrapper + .processPullResult(mq, pullResult, subscriptionData)); } }); } @@ -270,123 +393,224 @@ public void onException(Throwable e) { } - public PullResult pull(MessageQueue mq, String subExpression, long offset, int maxNums) + public PullResult pullBlockIfNotFound(MessageQueue mq, String subExpression, long offset, int maxNums) throws MQClientException, RemotingException, MQBrokerException, InterruptedException { - return this.pullSyncImpl(mq, subExpression, offset, maxNums, false); + return this.pullSyncImpl(mq, subExpression, offset, maxNums, true); } - public PullResult pullBlockIfNotFound(MessageQueue mq, String subExpression, long offset, int maxNums) - throws MQClientException, RemotingException, MQBrokerException, InterruptedException { - return this.pullSyncImpl(mq, subExpression, offset, maxNums, true); + public void pullBlockIfNotFound(MessageQueue mq, String subExpression, long offset, int maxNums, + PullCallback pullCallback) throws MQClientException, RemotingException, InterruptedException { + this.pullAsyncImpl(mq, subExpression, offset, maxNums, pullCallback, true); } - public void pull(MessageQueue mq, String subExpression, long offset, int maxNums, PullCallback pullCallback) - throws MQClientException, RemotingException, InterruptedException { - this.pullAsyncImpl(mq, subExpression, offset, maxNums, pullCallback, false); + public QueryResult queryMessage(String topic, String key, int maxNum, long begin, long end) + throws MQClientException, InterruptedException { + this.makeSureStateOK(); + return this.mQClientFactory.getMQAdminImpl().queryMessage(topic, key, maxNum, begin, end); } - public void pullBlockIfNotFound(MessageQueue mq, String subExpression, long offset, int maxNums, - PullCallback pullCallback) throws MQClientException, RemotingException, InterruptedException { - this.pullAsyncImpl(mq, subExpression, offset, maxNums, pullCallback, true); + public long searchOffset(MessageQueue mq, long timestamp) throws MQClientException { + this.makeSureStateOK(); + return this.mQClientFactory.getMQAdminImpl().searchOffset(mq, timestamp); } - public void updateConsumeOffset(MessageQueue mq, long offset) throws RemotingException, MQBrokerException, + public void sendMessageBack(MessageExt msg, int delayLevel) throws RemotingException, MQBrokerException, InterruptedException, MQClientException { - FindBrokerResult findBrokerResult = this.mQClientFactory.findBrokerAddressInAdmin(mq.getBrokerName()); - if (null == findBrokerResult) { - // TODO ˴ܶName ServerѹҪ - this.mQClientFactory.updateTopicRouteInfoFromNameServer(mq.getTopic()); - findBrokerResult = this.mQClientFactory.findBrokerAddressInAdmin(mq.getBrokerName()); + try { + this.mQClientFactory.getMQClientAPIImpl().consumerSendMessageBack(msg, + this.defaultMQPullConsumer.getConsumerGroup(), delayLevel, 3000); } + catch (Exception e) { + log.error("sendMessageBack Exception, " + this.defaultMQPullConsumer.getConsumerGroup(), e); + + Message newMsg = + new Message(MixAll.getRetryTopic(this.defaultMQPullConsumer.getConsumerGroup()), + msg.getBody()); - if (findBrokerResult != null) { - UpdateConsumerOffsetRequestHeader requestHeader = new UpdateConsumerOffsetRequestHeader(); - requestHeader.setTopic(mq.getTopic()); - requestHeader.setConsumerGroup(this.defaultMQPullConsumer.getConsumerGroup()); - requestHeader.setQueueId(mq.getQueueId()); - requestHeader.setCommitOffset(offset); + newMsg.setFlag(msg.getFlag()); + newMsg.setProperties(msg.getProperties()); + newMsg.putProperty(MessageConst.PROPERTY_RETRY_TOPIC, msg.getTopic()); - this.mQClientFactory.getMQClientAPIImpl().updateConsumerOffset(findBrokerResult.getBrokerAddr(), - requestHeader, 1000 * 5); + this.mQClientFactory.getDefaultMQProducer().send(newMsg); } - else { - throw new MQClientException("The broker[" + mq.getBrokerName() + "] not exist", null); + } + + + public void shutdown() { + switch (this.serviceState) { + case CREATE_JUST: + break; + case RUNNING: + this.persistConsumerOffset(); + this.mQClientFactory.unregisterConsumer(this.defaultMQPullConsumer.getConsumerGroup()); + this.mQClientFactory.shutdown(); + log.info("the consumer [{}] shutdown OK", this.defaultMQPullConsumer.getConsumerGroup()); + this.serviceState = ServiceState.SHUTDOWN_ALREADY; + break; + case SHUTDOWN_ALREADY: + break; + default: + break; } } - public long fetchConsumeOffset(MessageQueue mq) throws RemotingException, MQBrokerException, - InterruptedException, MQClientException { - FindBrokerResult findBrokerResult = this.mQClientFactory.findBrokerAddressInAdmin(mq.getBrokerName()); - if (null == findBrokerResult) { - // TODO ˴ܶName ServerѹҪ - this.mQClientFactory.updateTopicRouteInfoFromNameServer(mq.getTopic()); - findBrokerResult = this.mQClientFactory.findBrokerAddressInAdmin(mq.getBrokerName()); + public void start() throws MQClientException { + switch (this.serviceState) { + case CREATE_JUST: + this.serviceState = ServiceState.START_FAILED; + + this.checkConfig(); + + this.copySubscription(); + + this.mQClientFactory = + MQClientManager.getInstance().getAndCreateMQClientFactory(this.defaultMQPullConsumer); + + // 初始化Rebalance变量 + this.rebalanceImpl.setConsumerGroup(this.defaultMQPullConsumer.getConsumerGroup()); + this.rebalanceImpl.setMessageModel(this.defaultMQPullConsumer.getMessageModel()); + this.rebalanceImpl.setAllocateMessageQueueStrategy(this.defaultMQPullConsumer + .getAllocateMessageQueueStrategy()); + this.rebalanceImpl.setmQClientFactory(this.mQClientFactory); + + this.pullAPIWrapper = new PullAPIWrapper(// + mQClientFactory,// + this.defaultMQPullConsumer.getConsumerGroup()); + + if (this.defaultMQPullConsumer.getOffsetStore() != null) { + this.offsetStore = this.defaultMQPullConsumer.getOffsetStore(); + } + else { + // 广播消费/集群消费 + switch (this.defaultMQPullConsumer.getMessageModel()) { + case BROADCASTING: + this.offsetStore = + new LocalFileOffsetStore(this.mQClientFactory, + this.defaultMQPullConsumer.getConsumerGroup()); + break; + case CLUSTERING: + this.offsetStore = + new RemoteBrokerOffsetStore(this.mQClientFactory, + this.defaultMQPullConsumer.getConsumerGroup()); + break; + default: + break; + } + } + + // 加载消费进度 + this.offsetStore.load(); + + boolean registerOK = + mQClientFactory.registerConsumer(this.defaultMQPullConsumer.getConsumerGroup(), this); + if (!registerOK) { + this.serviceState = ServiceState.CREATE_JUST; + + throw new MQClientException("The consumer group[" + + this.defaultMQPullConsumer.getConsumerGroup() + + "] has been created before, specify another name please." + + FAQUrl.suggestTodo(FAQUrl.GROUP_NAME_DUPLICATE_URL), null); + } + + mQClientFactory.start(); + log.info("the consumer [{}] start OK", this.defaultMQPullConsumer.getConsumerGroup()); + this.serviceState = ServiceState.RUNNING; + break; + case RUNNING: + case START_FAILED: + case SHUTDOWN_ALREADY: + throw new MQClientException("The PullConsumer service state not OK, maybe started once, "// + + this.serviceState// + + FAQUrl.suggestTodo(FAQUrl.CLIENT_SERVICE_NOT_OK), null); + default: + break; } + } - if (findBrokerResult != null) { - QueryConsumerOffsetRequestHeader requestHeader = new QueryConsumerOffsetRequestHeader(); - requestHeader.setTopic(mq.getTopic()); - requestHeader.setConsumerGroup(this.defaultMQPullConsumer.getConsumerGroup()); - requestHeader.setQueueId(mq.getQueueId()); - return this.mQClientFactory.getMQClientAPIImpl().queryConsumerOffset( - findBrokerResult.getBrokerAddr(), requestHeader, 1000 * 5); + private void copySubscription() throws MQClientException { + try { + // 复制用户初始设置的订阅关系 + Set registerTopics = this.defaultMQPullConsumer.getRegisterTopics(); + if (registerTopics != null) { + for (final String topic : registerTopics) { + SubscriptionData subscriptionData = + FilterAPI.buildSubscriptionData(topic, SubscriptionData.SUB_ALL); + this.rebalanceImpl.getSubscriptionInner().put(topic, subscriptionData); + } + } } - else { - throw new MQClientException("The broker[" + mq.getBrokerName() + "] not exist", null); + catch (Exception e) { + throw new MQClientException("subscription exception", e); } } - public List fetchMessageQueuesInBalance(String topic) { - // TODO Auto-generated method stub - return null; - } + private void checkConfig() throws MQClientException { + // check consumerGroup + Validators.checkGroup(this.defaultMQPullConsumer.getConsumerGroup()); + // consumerGroup + if (null == this.defaultMQPullConsumer.getConsumerGroup()) { + throw new MQClientException("consumerGroup is null" // + + FAQUrl.suggestTodo(FAQUrl.CLIENT_PARAMETER_CHECK_URL), // + null); + } - public List fetchSubscribeMessageQueues(String topic) throws MQClientException { - return this.mQClientFactory.getMQAdminImpl().fetchSubscribeMessageQueues(topic); + // consumerGroup + if (this.defaultMQPullConsumer.getConsumerGroup().equals(MixAll.DEFAULT_CONSUMER_GROUP)) { + throw new MQClientException("consumerGroup can not equal "// + + MixAll.DEFAULT_CONSUMER_GROUP // + + ", please specify another one."// + + FAQUrl.suggestTodo(FAQUrl.CLIENT_PARAMETER_CHECK_URL), // + null); + } + + // messageModel + if (null == this.defaultMQPullConsumer.getMessageModel()) { + throw new MQClientException("messageModel is null" // + + FAQUrl.suggestTodo(FAQUrl.CLIENT_PARAMETER_CHECK_URL), // + null); + } + + // allocateMessageQueueStrategy + if (null == this.defaultMQPullConsumer.getAllocateMessageQueueStrategy()) { + throw new MQClientException("allocateMessageQueueStrategy is null" // + + FAQUrl.suggestTodo(FAQUrl.CLIENT_PARAMETER_CHECK_URL), // + null); + } } - @Override - public MessageModel getMessageModel() { - return MessageModel.UNKNOWNS; + public void updateConsumeOffset(MessageQueue mq, long offset) throws MQClientException { + this.makeSureStateOK(); + this.offsetStore.updateOffset(mq, offset, false); } - @Override - public ConsumeType getConsumeType() { - return ConsumeType.CONSUME_ACTIVELY; + public MessageExt viewMessage(String msgId) throws RemotingException, MQBrokerException, + InterruptedException, MQClientException { + this.makeSureStateOK(); + return this.mQClientFactory.getMQAdminImpl().viewMessage(msgId); } - @Override - public Set getMQSubscriptions() { - Set result = new HashSet(); + public DefaultMQPullConsumer getDefaultMQPullConsumer() { + return defaultMQPullConsumer; + } - Set topics = this.defaultMQPullConsumer.getRegisterTopics(); - if (topics != null) { - synchronized (topics) { - for (String t : topics) { - // TODO - SubscriptionData ms = new SubscriptionData(t, null, null, true); - result.add(ms); - } - } - } - return result; + public OffsetStore getOffsetStore() { + return offsetStore; } - @Override - public String getGroupName() { - return this.defaultMQPullConsumer.getConsumerGroup(); + public void setOffsetStore(OffsetStore offsetStore) { + this.offsetStore = offsetStore; } } diff --git a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/impl/consumer/DefaultMQPushConsumerImpl.java b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/impl/consumer/DefaultMQPushConsumerImpl.java index 87b0cacc..19b00105 100644 --- a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/impl/consumer/DefaultMQPushConsumerImpl.java +++ b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/impl/consumer/DefaultMQPushConsumerImpl.java @@ -1,34 +1,107 @@ /** - * $Id: DefaultMQPushConsumerImpl.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.client.impl.consumer; -import java.util.List; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; + +import org.slf4j.Logger; import com.alibaba.rocketmq.client.QueryResult; +import com.alibaba.rocketmq.client.Validators; import com.alibaba.rocketmq.client.consumer.DefaultMQPushConsumer; -import com.alibaba.rocketmq.client.consumer.MQPushConsumer; +import com.alibaba.rocketmq.client.consumer.PullCallback; +import com.alibaba.rocketmq.client.consumer.PullResult; import com.alibaba.rocketmq.client.consumer.listener.MessageListener; +import com.alibaba.rocketmq.client.consumer.listener.MessageListenerConcurrently; +import com.alibaba.rocketmq.client.consumer.listener.MessageListenerOrderly; +import com.alibaba.rocketmq.client.consumer.store.LocalFileOffsetStore; +import com.alibaba.rocketmq.client.consumer.store.OffsetStore; +import com.alibaba.rocketmq.client.consumer.store.ReadOffsetType; +import com.alibaba.rocketmq.client.consumer.store.RemoteBrokerOffsetStore; import com.alibaba.rocketmq.client.exception.MQBrokerException; import com.alibaba.rocketmq.client.exception.MQClientException; +import com.alibaba.rocketmq.client.hook.ConsumeMessageContext; +import com.alibaba.rocketmq.client.hook.ConsumeMessageHook; +import com.alibaba.rocketmq.client.impl.CommunicationMode; +import com.alibaba.rocketmq.client.impl.MQClientManager; import com.alibaba.rocketmq.client.impl.factory.MQClientFactory; -import com.alibaba.rocketmq.common.MessageExt; -import com.alibaba.rocketmq.common.MessageQueue; +import com.alibaba.rocketmq.client.log.ClientLogger; +import com.alibaba.rocketmq.client.stat.ConsumerStatManager; +import com.alibaba.rocketmq.common.MixAll; import com.alibaba.rocketmq.common.ServiceState; -import com.alibaba.rocketmq.common.TopicFilterType; +import com.alibaba.rocketmq.common.UtilAll; +import com.alibaba.rocketmq.common.consumer.ConsumeFromWhere; +import com.alibaba.rocketmq.common.filter.FilterAPI; +import com.alibaba.rocketmq.common.help.FAQUrl; +import com.alibaba.rocketmq.common.message.Message; +import com.alibaba.rocketmq.common.message.MessageConst; +import com.alibaba.rocketmq.common.message.MessageExt; +import com.alibaba.rocketmq.common.message.MessageQueue; +import com.alibaba.rocketmq.common.protocol.heartbeat.ConsumeType; +import com.alibaba.rocketmq.common.protocol.heartbeat.MessageModel; +import com.alibaba.rocketmq.common.protocol.heartbeat.SubscriptionData; +import com.alibaba.rocketmq.common.sysflag.PullSysFlag; import com.alibaba.rocketmq.remoting.exception.RemotingException; /** + * Push方式的Consumer实现 * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com - * + * @author shijia.wxr + * @since 2013-6-15 */ -public class DefaultMQPushConsumerImpl implements MQPushConsumer { +public class DefaultMQPushConsumerImpl implements MQConsumerInner { + // 拉消息异常时,延迟一段时间再拉 + private static final long PullTimeDelayMillsWhenException = 3000; + // 本地内存队列慢,流控间隔时间 + private static final long PullTimeDelayMillsWhenFlowControl = 50; + // 被挂起后,下次拉取间隔时间 + private static final long PullTimeDelayMillsWhenSuspend = 1000; + // 长轮询模式,Consumer连接在Broker挂起最长时间 + private static final long BrokerSuspendMaxTimeMillis = 1000 * 15; + // 长轮询模式,Consumer超时时间(必须要大于brokerSuspendMaxTimeMillis) + private static final long ConsumerTimeoutMillisWhenSuspend = 1000 * 30; + private final Logger log = ClientLogger.getLog(); private final DefaultMQPushConsumer defaultMQPushConsumer; + // Rebalance实现 + private final RebalanceImpl rebalanceImpl = new RebalancePushImpl(this); + private final ConsumerStatManager consumerStatManager = new ConsumerStatManager(); private ServiceState serviceState = ServiceState.CREATE_JUST; private MQClientFactory mQClientFactory; private PullAPIWrapper pullAPIWrapper; + // 是否暂停接收消息 suspend/resume + private volatile boolean pause = false; + // 是否顺序消费消息 + private boolean consumeOrderly = false; + // 消费消息监听器 + private MessageListener messageListenerInner; + // 消费进度存储 + private OffsetStore offsetStore; + // 消费消息服务 + private ConsumeMessageService consumeMessageService; + + /** + * 消费每条消息会回调 + */ + private final ArrayList hookList = new ArrayList(); public DefaultMQPushConsumerImpl(DefaultMQPushConsumer defaultMQPushConsumer) { @@ -36,116 +109,824 @@ public DefaultMQPushConsumerImpl(DefaultMQPushConsumer defaultMQPushConsumer) { } - @Override - public void sendMessageBack(MessageExt msg, MessageQueue mq, int delayLevel) { - // TODO Auto-generated method stub + public boolean hasHook() { + return !this.hookList.isEmpty(); + } + + + public void registerHook(final ConsumeMessageHook hook) { + this.hookList.add(hook); + log.info("register consumeMessageHook Hook, {}", hook.hookName()); + } + + + public void executeHookBefore(final ConsumeMessageContext context) { + if (!this.hookList.isEmpty()) { + for (ConsumeMessageHook hook : this.hookList) { + try { + hook.consumeMessageBefore(context); + } + catch (Throwable e) { + } + } + } + } + + + public void executeHookAfter(final ConsumeMessageContext context) { + if (!this.hookList.isEmpty()) { + for (ConsumeMessageHook hook : this.hookList) { + try { + hook.consumeMessageAfter(context); + } + catch (Throwable e) { + } + } + } + } + + + public void createTopic(String key, String newTopic, int queueNum) throws MQClientException { + this.mQClientFactory.getMQAdminImpl().createTopic(key, newTopic, queueNum); + } + + + public Set fetchSubscribeMessageQueues(String topic) throws MQClientException { + Set result = this.rebalanceImpl.getTopicSubscribeInfoTable().get(topic); + if (null == result) { + this.mQClientFactory.updateTopicRouteInfoFromNameServer(topic); + result = this.rebalanceImpl.getTopicSubscribeInfoTable().get(topic); + } + + if (null == result) { + throw new MQClientException("The topic[" + topic + "] not exist", null); + } + + return result; + } + + + public DefaultMQPushConsumer getDefaultMQPushConsumer() { + return defaultMQPushConsumer; + } + + + public long earliestMsgStoreTime(MessageQueue mq) throws MQClientException { + return this.mQClientFactory.getMQAdminImpl().earliestMsgStoreTime(mq); + } + + + public long maxOffset(MessageQueue mq) throws MQClientException { + return this.mQClientFactory.getMQAdminImpl().maxOffset(mq); + } + + + public long minOffset(MessageQueue mq) throws MQClientException { + return this.mQClientFactory.getMQAdminImpl().minOffset(mq); + } + + + public OffsetStore getOffsetStore() { + return offsetStore; + } + + + public void setOffsetStore(OffsetStore offsetStore) { + this.offsetStore = offsetStore; } @Override - public List fetchSubscribeMessageQueues(String topic) throws MQClientException { - // TODO Auto-generated method stub - return null; + public String groupName() { + return this.defaultMQPushConsumer.getConsumerGroup(); } @Override - public void createTopic(String key, String newTopic, int queueNum, TopicFilterType topicFilterType, - boolean order) throws MQClientException { - // TODO Auto-generated method stub + public MessageModel messageModel() { + return this.defaultMQPushConsumer.getMessageModel(); + } + + @Override + public ConsumeType consumeType() { + return ConsumeType.CONSUME_PASSIVELY; } @Override - public long searchOffset(MessageQueue mq, long timestamp) throws MQClientException { - // TODO Auto-generated method stub - return 0; + public ConsumeFromWhere consumeFromWhere() { + return this.defaultMQPushConsumer.getConsumeFromWhere(); } @Override - public long getMaxOffset(MessageQueue mq) throws MQClientException { - // TODO Auto-generated method stub - return 0; + public Set subscriptions() { + Set subSet = new HashSet(); + + subSet.addAll(this.rebalanceImpl.getSubscriptionInner().values()); + + return subSet; } @Override - public long getMinOffset(MessageQueue mq) throws MQClientException { - // TODO Auto-generated method stub - return 0; + public void doRebalance() { + if (this.rebalanceImpl != null) { + this.rebalanceImpl.doRebalance(); + } } @Override - public long getEarliestMsgStoreTime(MessageQueue mq) throws MQClientException { - // TODO Auto-generated method stub - return 0; + public void persistConsumerOffset() { + try { + this.makeSureStateOK(); + Set mqs = new HashSet(); + Set allocateMq = this.rebalanceImpl.getProcessQueueTable().keySet(); + if (allocateMq != null) { + mqs.addAll(allocateMq); + } + + this.offsetStore.persistAll(mqs); + } + catch (Exception e) { + log.error("group: " + this.defaultMQPushConsumer.getConsumerGroup() + + " persistConsumerOffset exception", e); + } } @Override - public MessageExt viewMessage(String msgId) throws RemotingException, MQBrokerException, - InterruptedException, MQClientException { - // TODO Auto-generated method stub - return null; + public void updateTopicSubscribeInfo(String topic, Set info) { + Map subTable = this.getSubscriptionInner(); + if (subTable != null) { + if (subTable.containsKey(topic)) { + this.rebalanceImpl.topicSubscribeInfoTable.put(topic, info); + } + } + } + + + public ConcurrentHashMap getSubscriptionInner() { + return this.rebalanceImpl.getSubscriptionInner(); } @Override + public boolean isSubscribeTopicNeedUpdate(String topic) { + Map subTable = this.getSubscriptionInner(); + if (subTable != null) { + if (subTable.containsKey(topic)) { + return !this.rebalanceImpl.topicSubscribeInfoTable.containsKey(topic); + } + } + + return false; + } + + + /** + * 通过Tag过滤时,会存在offset不准确的情况,需要纠正 + */ + private void correctTagsOffset(final PullRequest pullRequest) { + // 说明本地没有可消费的消息 + if (0L == pullRequest.getProcessQueue().getMsgCount().get()) { + this.offsetStore.updateOffset(pullRequest.getMessageQueue(), pullRequest.getNextOffset(), true); + } + } + + private long flowControlTimes1 = 0; + private long flowControlTimes2 = 0; + + + public void pullMessage(final PullRequest pullRequest) { + final ProcessQueue processQueue = pullRequest.getProcessQueue(); + if (processQueue.isDroped()) { + log.info("the pull request[{}] is droped.", pullRequest.toString()); + return; + } + + // 检测Consumer是否启动 + try { + this.makeSureStateOK(); + } + catch (MQClientException e) { + log.warn("pullMessage exception, consumer state not ok", e); + this.executePullRequestLater(pullRequest, PullTimeDelayMillsWhenException); + return; + } + + // 检测Consumer是否被挂起 + if (this.isPause()) { + this.executePullRequestLater(pullRequest, PullTimeDelayMillsWhenSuspend); + return; + } + + // 流量控制,队列中消息总数 + long size = processQueue.getMsgCount().get(); + if (size > this.defaultMQPushConsumer.getPullThresholdForQueue()) { + this.executePullRequestLater(pullRequest, PullTimeDelayMillsWhenFlowControl); + if ((flowControlTimes1++ % 3000) == 0) { + log.warn("the consumer message buffer is full, so do flow control, {} {} {}", size, + pullRequest, flowControlTimes1); + } + return; + } + + // 流量控制,队列中消息最大跨度 + if (!this.consumeOrderly) { + if (processQueue.getMaxSpan() > this.defaultMQPushConsumer.getConsumeConcurrentlyMaxSpan()) { + this.executePullRequestLater(pullRequest, PullTimeDelayMillsWhenFlowControl); + if ((flowControlTimes2++ % 3000) == 0) { + log.warn("the queue's messages, span too long, so do flow control, {} {} {}", + processQueue.getMaxSpan(), pullRequest, flowControlTimes2); + } + return; + } + } + + // 查询订阅关系 + final SubscriptionData subscriptionData = + this.rebalanceImpl.getSubscriptionInner().get(pullRequest.getMessageQueue().getTopic()); + if (null == subscriptionData) { + // 由于并发关系,即使找不到订阅关系,也要重试下,防止丢失PullRequest + this.executePullRequestLater(pullRequest, PullTimeDelayMillsWhenException); + log.warn("find the consumer's subscription failed, {}", pullRequest); + return; + } + + final long beginTimestamp = System.currentTimeMillis(); + + PullCallback pullCallback = new PullCallback() { + @Override + public void onSuccess(PullResult pullResult) { + if (pullResult != null) { + pullResult = + DefaultMQPushConsumerImpl.this.pullAPIWrapper.processPullResult( + pullRequest.getMessageQueue(), pullResult, subscriptionData); + + switch (pullResult.getPullStatus()) { + case FOUND: + pullRequest.setNextOffset(pullResult.getNextBeginOffset()); + + long pullRT = System.currentTimeMillis() - beginTimestamp; + DefaultMQPushConsumerImpl.this.getConsumerStatManager().getConsumertat() + .getPullTimesTotal().incrementAndGet(); + DefaultMQPushConsumerImpl.this.getConsumerStatManager().getConsumertat() + .getPullRTTotal().addAndGet(pullRT); + + boolean dispathToConsume = processQueue.putMessage(pullResult.getMsgFoundList()); + DefaultMQPushConsumerImpl.this.consumeMessageService.submitConsumeRequest(// + pullResult.getMsgFoundList(), // + processQueue, // + pullRequest.getMessageQueue(), // + dispathToConsume); + + // 流控 + if (DefaultMQPushConsumerImpl.this.defaultMQPushConsumer.getPullInterval() > 0) { + DefaultMQPushConsumerImpl.this.executePullRequestLater(pullRequest, + DefaultMQPushConsumerImpl.this.defaultMQPushConsumer.getPullInterval()); + } + // 立刻拉消息 + else { + DefaultMQPushConsumerImpl.this.executePullRequestImmediately(pullRequest); + } + + break; + case NO_NEW_MSG: + pullRequest.setNextOffset(pullResult.getNextBeginOffset()); + + DefaultMQPushConsumerImpl.this.correctTagsOffset(pullRequest); + + DefaultMQPushConsumerImpl.this.executePullRequestImmediately(pullRequest); + break; + case NO_MATCHED_MSG: + pullRequest.setNextOffset(pullResult.getNextBeginOffset()); + + DefaultMQPushConsumerImpl.this.executePullRequestImmediately(pullRequest); + break; + case OFFSET_ILLEGAL: + log.warn("the pull request offset illegal, {} {}",// + pullRequest.toString(), pullResult.toString()); + if (pullRequest.getNextOffset() < pullResult.getMinOffset()) { + pullRequest.setNextOffset(pullResult.getMinOffset()); + } + else if (pullRequest.getNextOffset() > pullResult.getMaxOffset()) { + pullRequest.setNextOffset(pullResult.getMaxOffset()); + } + + DefaultMQPushConsumerImpl.this.offsetStore.updateOffset( + pullRequest.getMessageQueue(), pullRequest.getNextOffset(), false); + + log.warn("fix the pull request offset, {}", pullRequest); + DefaultMQPushConsumerImpl.this.executePullRequestImmediately(pullRequest); + break; + default: + break; + } + } + } + + + @Override + public void onException(Throwable e) { + if (!pullRequest.getMessageQueue().getTopic().startsWith(MixAll.RETRY_GROUP_TOPIC_PREFIX)) { + log.warn("execute the pull request exception", e); + } + + DefaultMQPushConsumerImpl.this.executePullRequestLater(pullRequest, + PullTimeDelayMillsWhenException); + } + }; + + boolean commitOffsetEnable = false; + long commitOffsetValue = 0L; + if (MessageModel.CLUSTERING == this.defaultMQPushConsumer.getMessageModel()) { + commitOffsetValue = + this.offsetStore.readOffset(pullRequest.getMessageQueue(), + ReadOffsetType.READ_FROM_MEMORY); + if (commitOffsetValue > 0) { + commitOffsetEnable = true; + } + } + + String subExpression = null; + if (this.defaultMQPushConsumer.isPostSubscriptionWhenPull()) { + SubscriptionData sd = + this.rebalanceImpl.getSubscriptionInner().get(pullRequest.getMessageQueue().getTopic()); + if (sd != null) { + subExpression = sd.getSubString(); + } + } + + int sysFlag = PullSysFlag.buildSysFlag(// + commitOffsetEnable, // commitOffset + true, // suspend + subExpression != null// subscription + ); + try { + this.pullAPIWrapper.pullKernelImpl(// + pullRequest.getMessageQueue(), // 1 + subExpression, // 2 + subscriptionData.getSubVersion(), // 3 + pullRequest.getNextOffset(), // 4 + this.defaultMQPushConsumer.getPullBatchSize(), // 5 + sysFlag, // 6 + commitOffsetValue,// 7 + BrokerSuspendMaxTimeMillis, // 8 + ConsumerTimeoutMillisWhenSuspend, // 9 + CommunicationMode.ASYNC, // 10 + pullCallback// 11 + ); + } + catch (Exception e) { + log.error("pullKernelImpl exception", e); + this.executePullRequestLater(pullRequest, PullTimeDelayMillsWhenException); + } + } + + + /** + * 立刻执行这个PullRequest + */ + public void executePullRequestImmediately(final PullRequest pullRequest) { + this.mQClientFactory.getPullMessageService().executePullRequestImmediately(pullRequest); + } + + + /** + * 稍后再执行这个PullRequest + */ + private void executePullRequestLater(final PullRequest pullRequest, final long timeDelay) { + this.mQClientFactory.getPullMessageService().executePullRequestLater(pullRequest, timeDelay); + } + + + public boolean isPause() { + return pause; + } + + + public void setPause(boolean pause) { + this.pause = pause; + } + + + private void makeSureStateOK() throws MQClientException { + if (this.serviceState != ServiceState.RUNNING) { + throw new MQClientException("The consumer service state not OK, "// + + this.serviceState// + + FAQUrl.suggestTodo(FAQUrl.CLIENT_SERVICE_NOT_OK), null); + } + } + + + public ConsumerStatManager getConsumerStatManager() { + return consumerStatManager; + } + + public QueryResult queryMessage(String topic, String key, int maxNum, long begin, long end) throws MQClientException, InterruptedException { - // TODO Auto-generated method stub - return null; + return this.mQClientFactory.getMQAdminImpl().queryMessage(topic, key, maxNum, begin, end); } - @Override - public void start() { - // TODO Auto-generated method stub + public void registerMessageListener(MessageListener messageListener) { + this.messageListenerInner = messageListener; + } + + public void resume() { + this.pause = false; + log.info("resume this consumer, {}", this.defaultMQPushConsumer.getConsumerGroup()); + } + + + public long searchOffset(MessageQueue mq, long timestamp) throws MQClientException { + return this.mQClientFactory.getMQAdminImpl().searchOffset(mq, timestamp); + } + + + public void sendMessageBack(MessageExt msg, int delayLevel) throws RemotingException, MQBrokerException, + InterruptedException, MQClientException { + try { + this.mQClientFactory.getMQClientAPIImpl().consumerSendMessageBack(msg, + this.defaultMQPushConsumer.getConsumerGroup(), delayLevel, 3000); + } + catch (Exception e) { + log.error("sendMessageBack Exception, " + this.defaultMQPushConsumer.getConsumerGroup(), e); + + Message newMsg = + new Message(MixAll.getRetryTopic(this.defaultMQPushConsumer.getConsumerGroup()), + msg.getBody()); + + newMsg.setFlag(msg.getFlag()); + newMsg.setProperties(msg.getProperties()); + newMsg.putProperty(MessageConst.PROPERTY_RETRY_TOPIC, msg.getTopic()); + + this.mQClientFactory.getDefaultMQProducer().send(newMsg); + } } - @Override public void shutdown() { - // TODO Auto-generated method stub + switch (this.serviceState) { + case CREATE_JUST: + break; + case RUNNING: + this.consumeMessageService.shutdown(); + this.persistConsumerOffset(); + this.mQClientFactory.unregisterConsumer(this.defaultMQPushConsumer.getConsumerGroup()); + this.mQClientFactory.shutdown(); + log.info("the consumer [{}] shutdown OK", this.defaultMQPushConsumer.getConsumerGroup()); + this.serviceState = ServiceState.SHUTDOWN_ALREADY; + break; + case SHUTDOWN_ALREADY: + break; + default: + break; + } + } + + public void start() throws MQClientException { + switch (this.serviceState) { + case CREATE_JUST: + this.serviceState = ServiceState.START_FAILED; + + this.checkConfig(); + + // 复制订阅关系 + this.copySubscription(); + + this.mQClientFactory = + MQClientManager.getInstance().getAndCreateMQClientFactory(this.defaultMQPushConsumer); + + // 初始化Rebalance变量 + this.rebalanceImpl.setConsumerGroup(this.defaultMQPushConsumer.getConsumerGroup()); + this.rebalanceImpl.setMessageModel(this.defaultMQPushConsumer.getMessageModel()); + this.rebalanceImpl.setAllocateMessageQueueStrategy(this.defaultMQPushConsumer + .getAllocateMessageQueueStrategy()); + this.rebalanceImpl.setmQClientFactory(this.mQClientFactory); + + this.pullAPIWrapper = new PullAPIWrapper(// + mQClientFactory,// + this.defaultMQPushConsumer.getConsumerGroup()); + + if (this.defaultMQPushConsumer.getOffsetStore() != null) { + this.offsetStore = this.defaultMQPushConsumer.getOffsetStore(); + } + else { + // 广播消费/集群消费 + switch (this.defaultMQPushConsumer.getMessageModel()) { + case BROADCASTING: + this.offsetStore = + new LocalFileOffsetStore(this.mQClientFactory, + this.defaultMQPushConsumer.getConsumerGroup()); + break; + case CLUSTERING: + this.offsetStore = + new RemoteBrokerOffsetStore(this.mQClientFactory, + this.defaultMQPushConsumer.getConsumerGroup()); + break; + default: + break; + } + } + // 加载消费进度 + this.offsetStore.load(); + + // 启动消费消息服务 + if (this.getMessageListenerInner() instanceof MessageListenerOrderly) { + this.consumeOrderly = true; + this.consumeMessageService = + new ConsumeMessageOrderlyService(this, + (MessageListenerOrderly) this.getMessageListenerInner()); + } + else if (this.getMessageListenerInner() instanceof MessageListenerConcurrently) { + this.consumeOrderly = false; + this.consumeMessageService = + new ConsumeMessageConcurrentlyService(this, + (MessageListenerConcurrently) this.getMessageListenerInner()); + } + + this.consumeMessageService.start(); + + boolean registerOK = + mQClientFactory.registerConsumer(this.defaultMQPushConsumer.getConsumerGroup(), this); + if (!registerOK) { + this.serviceState = ServiceState.CREATE_JUST; + this.consumeMessageService.shutdown(); + throw new MQClientException("The consumer group[" + + this.defaultMQPushConsumer.getConsumerGroup() + + "] has been created before, specify another name please." + + FAQUrl.suggestTodo(FAQUrl.GROUP_NAME_DUPLICATE_URL), null); + } + + mQClientFactory.start(); + log.info("the consumer [{}] start OK", this.defaultMQPushConsumer.getConsumerGroup()); + this.serviceState = ServiceState.RUNNING; + break; + case RUNNING: + case START_FAILED: + case SHUTDOWN_ALREADY: + throw new MQClientException("The PushConsumer service state not OK, maybe started once, "// + + this.serviceState// + + FAQUrl.suggestTodo(FAQUrl.CLIENT_SERVICE_NOT_OK), null); + default: + break; + } + + this.updateTopicSubscribeInfoWhenSubscriptionChanged(); + + this.mQClientFactory.sendHeartbeatToAllBrokerWithLock(); + + this.mQClientFactory.rebalanceImmediately(); } - @Override - public void registerMessageListener(MessageListener messageListener) { - // TODO Auto-generated method stub + private void checkConfig() throws MQClientException { + // consumerGroup 有效性检查 + Validators.checkGroup(this.defaultMQPushConsumer.getConsumerGroup()); + + // consumerGroup + if (null == this.defaultMQPushConsumer.getConsumerGroup()) { + throw new MQClientException("consumerGroup is null" // + + FAQUrl.suggestTodo(FAQUrl.CLIENT_PARAMETER_CHECK_URL), // + null); + } + + // consumerGroup + if (this.defaultMQPushConsumer.getConsumerGroup().equals(MixAll.DEFAULT_CONSUMER_GROUP)) { + throw new MQClientException("consumerGroup can not equal "// + + MixAll.DEFAULT_CONSUMER_GROUP // + + ", please specify another one."// + + FAQUrl.suggestTodo(FAQUrl.CLIENT_PARAMETER_CHECK_URL), // + null); + } + + // messageModel + if (null == this.defaultMQPushConsumer.getMessageModel()) { + throw new MQClientException("messageModel is null" // + + FAQUrl.suggestTodo(FAQUrl.CLIENT_PARAMETER_CHECK_URL), // + null); + } + + // consumeFromWhereOffset + if (null == this.defaultMQPushConsumer.getConsumeFromWhere()) { + throw new MQClientException("consumeFromWhere is null" // + + FAQUrl.suggestTodo(FAQUrl.CLIENT_PARAMETER_CHECK_URL), // + null); + } + + // 校验回溯时间戳格式是否正确 + Date dt = UtilAll.parseDate(this.defaultMQPushConsumer.getConsumeTimestamp(), UtilAll.yyyyMMddHHmmss); + if (null == dt) { + throw new MQClientException("consumeTimestamp is invalid, yyyyMMddHHmmss" // + + FAQUrl.suggestTodo(FAQUrl.CLIENT_PARAMETER_CHECK_URL), // + null); + } + + // allocateMessageQueueStrategy + if (null == this.defaultMQPushConsumer.getAllocateMessageQueueStrategy()) { + throw new MQClientException("allocateMessageQueueStrategy is null" // + + FAQUrl.suggestTodo(FAQUrl.CLIENT_PARAMETER_CHECK_URL), // + null); + } + + // subscription + if (null == this.defaultMQPushConsumer.getSubscription()) { + throw new MQClientException("subscription is null" // + + FAQUrl.suggestTodo(FAQUrl.CLIENT_PARAMETER_CHECK_URL), // + null); + } + + // messageListener + if (null == this.defaultMQPushConsumer.getMessageListener()) { + throw new MQClientException("messageListener is null" // + + FAQUrl.suggestTodo(FAQUrl.CLIENT_PARAMETER_CHECK_URL), // + null); + } + + boolean orderly = this.defaultMQPushConsumer.getMessageListener() instanceof MessageListenerOrderly; + boolean concurrently = + this.defaultMQPushConsumer.getMessageListener() instanceof MessageListenerConcurrently; + if (!orderly && !concurrently) { + throw new MQClientException( + "messageListener must be instanceof MessageListenerOrderly or MessageListenerConcurrently" // + + FAQUrl.suggestTodo(FAQUrl.CLIENT_PARAMETER_CHECK_URL), // + null); + } + + // consumeThreadMin + if (this.defaultMQPushConsumer.getConsumeThreadMin() < 1 // + || this.defaultMQPushConsumer.getConsumeThreadMin() > 1000// + || this.defaultMQPushConsumer.getConsumeThreadMin() > this.defaultMQPushConsumer + .getConsumeThreadMax()// + ) { + throw new MQClientException("consumeThreadMin Out of range [1, 1000]" // + + FAQUrl.suggestTodo(FAQUrl.CLIENT_PARAMETER_CHECK_URL), // + null); + } + + // consumeThreadMax + if (this.defaultMQPushConsumer.getConsumeThreadMax() < 1 + || this.defaultMQPushConsumer.getConsumeThreadMax() > 1000) { + throw new MQClientException("consumeThreadMax Out of range [1, 1000]" // + + FAQUrl.suggestTodo(FAQUrl.CLIENT_PARAMETER_CHECK_URL), // + null); + } + + // consumeConcurrentlyMaxSpan + if (this.defaultMQPushConsumer.getConsumeConcurrentlyMaxSpan() < 1 + || this.defaultMQPushConsumer.getConsumeConcurrentlyMaxSpan() > 65535) { + throw new MQClientException("consumeConcurrentlyMaxSpan Out of range [1, 65535]" // + + FAQUrl.suggestTodo(FAQUrl.CLIENT_PARAMETER_CHECK_URL), // + null); + } + + // pullThresholdForQueue + if (this.defaultMQPushConsumer.getPullThresholdForQueue() < 1 + || this.defaultMQPushConsumer.getPullThresholdForQueue() > 65535) { + throw new MQClientException("pullThresholdForQueue Out of range [1, 65535]" // + + FAQUrl.suggestTodo(FAQUrl.CLIENT_PARAMETER_CHECK_URL), // + null); + } + + // pullInterval + if (this.defaultMQPushConsumer.getPullInterval() < 0 + || this.defaultMQPushConsumer.getPullInterval() > 65535) { + throw new MQClientException("pullInterval Out of range [0, 65535]" // + + FAQUrl.suggestTodo(FAQUrl.CLIENT_PARAMETER_CHECK_URL), // + null); + } + + // consumeMessageBatchMaxSize + if (this.defaultMQPushConsumer.getConsumeMessageBatchMaxSize() < 1 + || this.defaultMQPushConsumer.getConsumeMessageBatchMaxSize() > 1024) { + throw new MQClientException("consumeMessageBatchMaxSize Out of range [1, 1024]" // + + FAQUrl.suggestTodo(FAQUrl.CLIENT_PARAMETER_CHECK_URL), // + null); + } + + // pullBatchSize + if (this.defaultMQPushConsumer.getPullBatchSize() < 1 + || this.defaultMQPushConsumer.getPullBatchSize() > 1024) { + throw new MQClientException("pullBatchSize Out of range [1, 1024]" // + + FAQUrl.suggestTodo(FAQUrl.CLIENT_PARAMETER_CHECK_URL), // + null); + } + } + + private void copySubscription() throws MQClientException { + try { + // 复制用户初始设置的订阅关系 + Map sub = this.defaultMQPushConsumer.getSubscription(); + if (sub != null) { + for (final Map.Entry entry : sub.entrySet()) { + final String topic = entry.getKey(); + final String subString = entry.getValue(); + SubscriptionData subscriptionData = FilterAPI.buildSubscriptionData(topic, subString); + this.rebalanceImpl.getSubscriptionInner().put(topic, subscriptionData); + } + } + + if (null == this.messageListenerInner) { + this.messageListenerInner = this.defaultMQPushConsumer.getMessageListener(); + } + + switch (this.defaultMQPushConsumer.getMessageModel()) { + case BROADCASTING: + break; + case CLUSTERING: + // 默认订阅消息重试Topic + final String retryTopic = MixAll.getRetryTopic(this.defaultMQPushConsumer.getConsumerGroup()); + SubscriptionData subscriptionData = + FilterAPI.buildSubscriptionData(retryTopic, SubscriptionData.SUB_ALL); + this.rebalanceImpl.getSubscriptionInner().put(retryTopic, subscriptionData); + break; + default: + break; + } + } + catch (Exception e) { + throw new MQClientException("subscription exception", e); + } } - @Override - public void subscribe(String topic, String subExpression) { - // TODO Auto-generated method stub + public MessageListener getMessageListenerInner() { + return messageListenerInner; + } + + private void updateTopicSubscribeInfoWhenSubscriptionChanged() { + Map subTable = this.getSubscriptionInner(); + if (subTable != null) { + for (final Map.Entry entry : subTable.entrySet()) { + final String topic = entry.getKey(); + this.mQClientFactory.updateTopicRouteInfoFromNameServer(topic); + } + } + } + + + public void subscribe(String topic, String subExpression) throws MQClientException { + try { + SubscriptionData subscriptionData = FilterAPI.buildSubscriptionData(topic, subExpression); + this.rebalanceImpl.getSubscriptionInner().put(topic, subscriptionData); + // 发送心跳,将变更的订阅关系注册上去 + if (this.mQClientFactory != null) { + this.mQClientFactory.sendHeartbeatToAllBrokerWithLock(); + } + } + catch (Exception e) { + throw new MQClientException("subscription exception", e); + } + } + + + public void suspend() { + this.pause = true; + log.info("suspend this consumer, {}", this.defaultMQPushConsumer.getConsumerGroup()); } - @Override public void unsubscribe(String topic) { - // TODO Auto-generated method stub + this.rebalanceImpl.getSubscriptionInner().remove(topic); + } + + public void updateConsumeOffset(MessageQueue mq, long offset) { + this.offsetStore.updateOffset(mq, offset, false); } - @Override - public void suspend() { - // TODO Auto-generated method stub + public void updateCorePoolSize(int corePoolSize) { + this.consumeMessageService.updateCorePoolSize(corePoolSize); + } + + public MessageExt viewMessage(String msgId) throws RemotingException, MQBrokerException, + InterruptedException, MQClientException { + return this.mQClientFactory.getMQAdminImpl().viewMessage(msgId); } - @Override - public void resume() { - // TODO Auto-generated method stub + public RebalanceImpl getRebalanceImpl() { + return rebalanceImpl; + } + + + public boolean isConsumeOrderly() { + return consumeOrderly; + } + + public void setConsumeOrderly(boolean consumeOrderly) { + this.consumeOrderly = consumeOrderly; } } diff --git a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/impl/consumer/MQConsumerInner.java b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/impl/consumer/MQConsumerInner.java index 33a2d0c0..6b8048f7 100644 --- a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/impl/consumer/MQConsumerInner.java +++ b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/impl/consumer/MQConsumerInner.java @@ -1,28 +1,59 @@ /** - * $Id: MQConsumerInner.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.client.impl.consumer; import java.util.Set; +import com.alibaba.rocketmq.common.consumer.ConsumeFromWhere; +import com.alibaba.rocketmq.common.message.MessageQueue; import com.alibaba.rocketmq.common.protocol.heartbeat.ConsumeType; import com.alibaba.rocketmq.common.protocol.heartbeat.MessageModel; import com.alibaba.rocketmq.common.protocol.heartbeat.SubscriptionData; /** - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * Consumer内部接口,供MQClientFactory使用 * + * @author shijia.wxr + * @since 2013-7-24 */ public interface MQConsumerInner { - public String getGroupName(); + public String groupName(); - public MessageModel getMessageModel(); + public MessageModel messageModel(); - public ConsumeType getConsumeType(); + public ConsumeType consumeType(); - public Set getMQSubscriptions(); + public ConsumeFromWhere consumeFromWhere(); + + + public Set subscriptions(); + + + public void doRebalance(); + + + public void persistConsumerOffset(); + + + public void updateTopicSubscribeInfo(final String topic, final Set info); + + + public boolean isSubscribeTopicNeedUpdate(final String topic); } diff --git a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/impl/consumer/MessageQueueLock.java b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/impl/consumer/MessageQueueLock.java new file mode 100644 index 00000000..a03a2799 --- /dev/null +++ b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/impl/consumer/MessageQueueLock.java @@ -0,0 +1,46 @@ +/** + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.rocketmq.client.impl.consumer; + +import java.util.concurrent.ConcurrentHashMap; + +import com.alibaba.rocketmq.common.message.MessageQueue; + + +/** + * 严格保证单个队列同一时刻只有一个线程消费 + * + * @author shijia.wxr + * @since 2013-6-25 + */ +public class MessageQueueLock { + private ConcurrentHashMap mqLockTable = + new ConcurrentHashMap(); + + + public Object fetchLockObject(final MessageQueue mq) { + Object objLock = this.mqLockTable.get(mq); + if (null == objLock) { + objLock = new Object(); + Object prevLock = this.mqLockTable.putIfAbsent(mq, objLock); + if (prevLock != null) { + objLock = prevLock; + } + } + + return objLock; + } +} diff --git a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/impl/consumer/ProcessQueue.java b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/impl/consumer/ProcessQueue.java new file mode 100644 index 00000000..acf3e320 --- /dev/null +++ b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/impl/consumer/ProcessQueue.java @@ -0,0 +1,335 @@ +/** + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.rocketmq.client.impl.consumer; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; +import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.locks.ReadWriteLock; +import java.util.concurrent.locks.ReentrantReadWriteLock; + +import org.slf4j.Logger; + +import com.alibaba.rocketmq.client.log.ClientLogger; +import com.alibaba.rocketmq.common.message.MessageExt; + + +/** + * 正在被消费的队列,含消息 + * + * @author shijia.wxr + * @since 2013-7-24 + */ +public class ProcessQueue { + // 客户端本地Lock存活最大时间,超过则自动过期,单位ms + public final static long RebalanceLockMaxLiveTime = Long.parseLong(System.getProperty( + "rocketmq.client.rebalance.lockMaxLiveTime", "30000")); + // 定时Lock间隔时间,单位ms + public final static long RebalanceLockInterval = Long.parseLong(System.getProperty( + "rocketmq.client.rebalance.lockInterval", "20000")); + + private final Logger log = ClientLogger.getLog(); + private final ReadWriteLock lockTreeMap = new ReentrantReadWriteLock(); + private final TreeMap msgTreeMap = new TreeMap(); + private volatile long queueOffsetMax = 0L; + private final AtomicLong msgCount = new AtomicLong(); + + // 当前Q是否被rebalance丢弃 + private volatile boolean droped = false; + + /** + * 顺序消息专用 + */ + // 是否从Broker锁定 + private volatile boolean locked = false; + // 最后一次锁定成功时间戳 + private volatile long lastLockTimestamp = System.currentTimeMillis(); + // 是否正在被消费 + private volatile boolean consuming = false; + // 事务方式消费,未提交的消息 + private final TreeMap msgTreeMapTemp = new TreeMap(); + + + public boolean isLockExpired() { + boolean result = (System.currentTimeMillis() - this.lastLockTimestamp) > RebalanceLockMaxLiveTime; + return result; + } + + + /** + * @return 是否需要分发当前队列到消费线程池 + */ + public boolean putMessage(final List msgs) { + boolean dispathToConsume = false; + try { + this.lockTreeMap.writeLock().lockInterruptibly(); + try { + int validMsgCnt = 0; + for (MessageExt msg : msgs) { + MessageExt old = msgTreeMap.put(msg.getQueueOffset(), msg); + if (null == old) { + validMsgCnt++; + this.queueOffsetMax = msg.getQueueOffset(); + } + } + msgCount.addAndGet(validMsgCnt); + + if (!msgTreeMap.isEmpty() && !this.consuming) { + dispathToConsume = true; + this.consuming = true; + } + } + finally { + this.lockTreeMap.writeLock().unlock(); + } + } + catch (InterruptedException e) { + log.error("putMessage exception", e); + } + + return dispathToConsume; + } + + + /** + * 获取当前队列的最大跨度 + */ + public long getMaxSpan() { + try { + this.lockTreeMap.readLock().lockInterruptibly(); + try { + if (!this.msgTreeMap.isEmpty()) { + return this.msgTreeMap.lastKey() - this.msgTreeMap.firstKey(); + } + } + finally { + this.lockTreeMap.readLock().unlock(); + } + } + catch (InterruptedException e) { + log.error("getMaxSpan exception", e); + } + + return 0; + } + + + /** + * 删除已经消费过的消息,返回最小Offset,这个Offset对应的消息未消费 + * + * @param msgs + * @return + */ + public long removeMessage(final List msgs) { + long result = -1; + + try { + this.lockTreeMap.writeLock().lockInterruptibly(); + try { + if (!msgTreeMap.isEmpty()) { + result = this.queueOffsetMax + 1; + int removedCnt = 0; + for (MessageExt msg : msgs) { + MessageExt prev = msgTreeMap.remove(msg.getQueueOffset()); + if (prev != null) { + removedCnt--; + } + } + msgCount.addAndGet(removedCnt); + + if (!msgTreeMap.isEmpty()) { + result = msgTreeMap.firstKey(); + } + } + } + finally { + this.lockTreeMap.writeLock().unlock(); + } + } + catch (InterruptedException e) { + log.error("removeMessage exception", e); + } + + return result; + } + + + public TreeMap getMsgTreeMap() { + return msgTreeMap; + } + + + public AtomicLong getMsgCount() { + return msgCount; + } + + + public boolean isDroped() { + return droped; + } + + + public void setDroped(boolean droped) { + this.droped = droped; + } + + + /** + * ======================================================================== + * 以下部分为顺序消息专有操作 + */ + + public void setLocked(boolean locked) { + this.locked = locked; + } + + + public boolean isLocked() { + return locked; + } + + + public void rollback() { + try { + this.lockTreeMap.writeLock().lockInterruptibly(); + try { + this.msgTreeMap.putAll(this.msgTreeMapTemp); + this.msgTreeMapTemp.clear(); + } + finally { + this.lockTreeMap.writeLock().unlock(); + } + } + catch (InterruptedException e) { + log.error("rollback exception", e); + } + } + + + public long commit() { + try { + this.lockTreeMap.writeLock().lockInterruptibly(); + try { + Long offset = this.msgTreeMapTemp.lastKey(); + msgCount.addAndGet(this.msgTreeMapTemp.size() * (-1)); + this.msgTreeMapTemp.clear(); + if (offset != null) { + return offset + 1; + } + } + finally { + this.lockTreeMap.writeLock().unlock(); + } + } + catch (InterruptedException e) { + log.error("commit exception", e); + } + + return -1; + } + + + public void makeMessageToCosumeAgain(List msgs) { + try { + this.lockTreeMap.writeLock().lockInterruptibly(); + try { + // 临时Table删除 + // 正常Table增加 + for (MessageExt msg : msgs) { + this.msgTreeMapTemp.remove(msg.getQueueOffset()); + this.msgTreeMap.put(msg.getQueueOffset(), msg); + } + } + finally { + this.lockTreeMap.writeLock().unlock(); + } + } + catch (InterruptedException e) { + log.error("makeMessageToCosumeAgain exception", e); + } + } + + + /** + * 如果取不到消息,则将正在消费状态置为false + * + * @param batchSize + * @return + */ + public List takeMessags(final int batchSize) { + List result = new ArrayList(batchSize); + try { + this.lockTreeMap.writeLock().lockInterruptibly(); + try { + if (!this.msgTreeMap.isEmpty()) { + for (int i = 0; i < batchSize; i++) { + Map.Entry entry = this.msgTreeMap.pollFirstEntry(); + if (entry != null) { + result.add(entry.getValue()); + msgTreeMapTemp.put(entry.getKey(), entry.getValue()); + } + else { + break; + } + } + } + + if (result.isEmpty()) { + consuming = false; + } + } + finally { + this.lockTreeMap.writeLock().unlock(); + } + } + catch (InterruptedException e) { + log.error("takeMessags exception", e); + } + + return result; + } + + + public void clear() { + try { + this.lockTreeMap.writeLock().lockInterruptibly(); + try { + this.msgTreeMap.clear(); + this.msgTreeMapTemp.clear(); + this.msgCount.set(0); + this.queueOffsetMax = 0L; + } + finally { + this.lockTreeMap.writeLock().unlock(); + } + } + catch (InterruptedException e) { + log.error("rollback exception", e); + } + } + + + public long getLastLockTimestamp() { + return lastLockTimestamp; + } + + + public void setLastLockTimestamp(long lastLockTimestamp) { + this.lastLockTimestamp = lastLockTimestamp; + } +} diff --git a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/impl/consumer/PullAPIWrapper.java b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/impl/consumer/PullAPIWrapper.java index b944dbea..c068259f 100644 --- a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/impl/consumer/PullAPIWrapper.java +++ b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/impl/consumer/PullAPIWrapper.java @@ -1,107 +1,186 @@ /** - * $Id: PullAPIWrapper.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.client.impl.consumer; +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicLong; +import com.alibaba.rocketmq.client.VirtualEnvUtil; import com.alibaba.rocketmq.client.consumer.PullCallback; -import com.alibaba.rocketmq.client.consumer.ConsumeFromWhichNode; import com.alibaba.rocketmq.client.consumer.PullResult; +import com.alibaba.rocketmq.client.consumer.PullStatus; import com.alibaba.rocketmq.client.exception.MQBrokerException; import com.alibaba.rocketmq.client.exception.MQClientException; import com.alibaba.rocketmq.client.impl.CommunicationMode; import com.alibaba.rocketmq.client.impl.FindBrokerResult; import com.alibaba.rocketmq.client.impl.factory.MQClientFactory; -import com.alibaba.rocketmq.common.MessageQueue; +import com.alibaba.rocketmq.common.MixAll; +import com.alibaba.rocketmq.common.UtilAll; +import com.alibaba.rocketmq.common.message.MessageConst; +import com.alibaba.rocketmq.common.message.MessageDecoder; +import com.alibaba.rocketmq.common.message.MessageExt; +import com.alibaba.rocketmq.common.message.MessageQueue; import com.alibaba.rocketmq.common.protocol.header.PullMessageRequestHeader; +import com.alibaba.rocketmq.common.protocol.heartbeat.SubscriptionData; import com.alibaba.rocketmq.common.sysflag.PullSysFlag; import com.alibaba.rocketmq.remoting.exception.RemotingException; /** - * Pullӿڽнһķװ - * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * 对Pull接口进行进一步的封装 * + * @author shijia.wxr + * @since 2013-7-24 */ public class PullAPIWrapper { - private ConcurrentHashMap pullFromWhichNodeTable = - new ConcurrentHashMap(32); + private ConcurrentHashMap pullFromWhichNodeTable = + new ConcurrentHashMap(32); private final MQClientFactory mQClientFactory; private final String consumerGroup; - private final ConsumeFromWhichNode consumeFromWhichNode; - public PullAPIWrapper(MQClientFactory mQClientFactory, String consumerGroup, - final ConsumeFromWhichNode pullFromWhere) { + public PullAPIWrapper(MQClientFactory mQClientFactory, String consumerGroup) { this.mQClientFactory = mQClientFactory; this.consumerGroup = consumerGroup; - this.consumeFromWhichNode = pullFromWhere; } - public void updatePullFromWhichNode(final MessageQueue mq, final boolean suggestPullingFromSlave) { - AtomicBoolean suggest = this.pullFromWhichNodeTable.get(mq); + public void updatePullFromWhichNode(final MessageQueue mq, final long brokerId) { + AtomicLong suggest = this.pullFromWhichNodeTable.get(mq); if (null == suggest) { - this.pullFromWhichNodeTable.put(mq, new AtomicBoolean(suggestPullingFromSlave)); + this.pullFromWhichNodeTable.put(mq, new AtomicLong(brokerId)); } else { - suggest.set(suggestPullingFromSlave); + suggest.set(brokerId); } } /** - * ÿжӦӦıĸ + * 对拉取结果进行处理,主要是消息反序列化 + * + * @param mq + * @param pullResult + * @param subscriptionData + * @param projectGroupPrefix + * 虚拟环境projectGroupPrefix,不存在可设置为 null + * @return */ - public ConsumeFromWhichNode recalculatePullFromWhichNode(final MessageQueue mq) { - switch (this.consumeFromWhichNode) { - case CONSUME_FROM_MASTER_FIRST: - AtomicBoolean suggest = this.pullFromWhichNodeTable.get(mq); - if (suggest != null) { - if (suggest.get()) { - return ConsumeFromWhichNode.CONSUME_FROM_SLAVE_FIRST; + public PullResult processPullResult(final MessageQueue mq, final PullResult pullResult, + final SubscriptionData subscriptionData) { + final String projectGroupPrefix = this.mQClientFactory.getMQClientAPIImpl().getProjectGroupPrefix(); + PullResultExt pullResultExt = (PullResultExt) pullResult; + + this.updatePullFromWhichNode(mq, pullResultExt.getSuggestWhichBrokerId()); + if (PullStatus.FOUND == pullResult.getPullStatus()) { + ByteBuffer byteBuffer = ByteBuffer.wrap(pullResultExt.getMessageBinary()); + List msgList = MessageDecoder.decodes(byteBuffer); + + // 消息再次过滤 + List msgListFilterAgain = msgList; + if (!subscriptionData.getTagsSet().isEmpty()) { + msgListFilterAgain = new ArrayList(msgList.size()); + for (MessageExt msg : msgList) { + if (msg.getTags() != null) { + if (subscriptionData.getTagsSet().contains(msg.getTags())) { + msgListFilterAgain.add(msg); + } + } + } + } + + // 清除虚拟运行环境相关的projectGroupPrefix + if (!UtilAll.isBlank(projectGroupPrefix)) { + subscriptionData.setTopic(VirtualEnvUtil.clearProjectGroup(subscriptionData.getTopic(), + projectGroupPrefix)); + mq.setTopic(VirtualEnvUtil.clearProjectGroup(mq.getTopic(), projectGroupPrefix)); + for (MessageExt msg : msgListFilterAgain) { + msg.setTopic(VirtualEnvUtil.clearProjectGroup(msg.getTopic(), projectGroupPrefix)); + // 消息中放入队列的最大最小Offset,方便应用来感知消息堆积程度 + msg.putProperty(MessageConst.PROPERTY_MIN_OFFSET, + Long.toString(pullResult.getMinOffset())); + msg.putProperty(MessageConst.PROPERTY_MAX_OFFSET, + Long.toString(pullResult.getMaxOffset())); + } + } + else { + // 消息中放入队列的最大最小Offset,方便应用来感知消息堆积程度 + for (MessageExt msg : msgListFilterAgain) { + msg.putProperty(MessageConst.PROPERTY_MIN_OFFSET, + Long.toString(pullResult.getMinOffset())); + msg.putProperty(MessageConst.PROPERTY_MAX_OFFSET, + Long.toString(pullResult.getMaxOffset())); } } - return ConsumeFromWhichNode.CONSUME_FROM_MASTER_FIRST; - default: - break; + pullResultExt.setMsgFoundList(msgListFilterAgain); } - return this.consumeFromWhichNode; + + // 令GC释放内存 + pullResultExt.setMessageBinary(null); + + return pullResult; + } + + + /** + * 每个队列都应该有相应的变量来保存从哪个服务器拉 + */ + public long recalculatePullFromWhichNode(final MessageQueue mq) { + AtomicLong suggest = this.pullFromWhichNodeTable.get(mq); + if (suggest != null) { + return suggest.get(); + } + + return MixAll.MASTER_ID; } public PullResult pullKernelImpl(// final MessageQueue mq,// 1 final String subExpression,// 2 - final long offset,// 3 - final int maxNums,// 4 - final int sysFlag,// 5 - final long commitOffset,// 6 - final long brokerSuspendMaxTimeMillis,// 7 - final long timeoutMillis,// 8 - final CommunicationMode communicationMode,// 9 - final PullCallback pullCallback// 10 + final long subVersion,// 3 + final long offset,// 4 + final int maxNums,// 5 + final int sysFlag,// 6 + final long commitOffset,// 7 + final long brokerSuspendMaxTimeMillis,// 8 + final long timeoutMillis,// 9 + final CommunicationMode communicationMode,// 10 + final PullCallback pullCallback// 11 ) throws MQClientException, RemotingException, MQBrokerException, InterruptedException { FindBrokerResult findBrokerResult = this.mQClientFactory.findBrokerAddressInSubscribe(mq.getBrokerName(), - this.recalculatePullFromWhichNode(mq)); + this.recalculatePullFromWhichNode(mq), false); if (null == findBrokerResult) { - // TODO ˴ܶName ServerѹҪ + // TODO 此处可能对Name Server压力过大,需要调优 this.mQClientFactory.updateTopicRouteInfoFromNameServer(mq.getTopic()); findBrokerResult = this.mQClientFactory.findBrokerAddressInSubscribe(mq.getBrokerName(), - this.recalculatePullFromWhichNode(mq)); + this.recalculatePullFromWhichNode(mq), false); } if (findBrokerResult != null) { int sysFlagInner = sysFlag; - // SlaveʵʱύѽȣԶʱύ + // Slave不允许实时提交消费进度,可以定时提交 if (findBrokerResult.isSlave()) { sysFlagInner = PullSysFlag.clearCommitOffsetFlag(sysFlagInner); } @@ -116,6 +195,7 @@ public PullResult pullKernelImpl(// requestHeader.setCommitOffset(commitOffset); requestHeader.setSuspendTimeoutMillis(brokerSuspendMaxTimeMillis); requestHeader.setSubscription(subExpression); + requestHeader.setSubVersion(subVersion); PullResult pullResult = this.mQClientFactory.getMQClientAPIImpl().pullMessage(// findBrokerResult.getBrokerAddr(),// diff --git a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/impl/consumer/PullMessageService.java b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/impl/consumer/PullMessageService.java index f3b310a3..701bad30 100644 --- a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/impl/consumer/PullMessageService.java +++ b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/impl/consumer/PullMessageService.java @@ -1,23 +1,50 @@ /** - * $Id: PullMessageService.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.client.impl.consumer; +import java.util.concurrent.Executors; import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.TimeUnit; + +import org.slf4j.Logger; import com.alibaba.rocketmq.client.impl.factory.MQClientFactory; +import com.alibaba.rocketmq.client.log.ClientLogger; import com.alibaba.rocketmq.common.ServiceThread; /** - * ѯϢ񣬵߳첽ȡ - * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * 长轮询拉消息服务,单线程异步拉取 * + * @author shijia.wxr + * @since 2013-7-24 */ public class PullMessageService extends ServiceThread { + private final Logger log = ClientLogger.getLog(); private final LinkedBlockingQueue pullRequestQueue = new LinkedBlockingQueue(); private final MQClientFactory mQClientFactory; + private final ScheduledExecutorService scheduledExecutorService = Executors + .newSingleThreadScheduledExecutor(new ThreadFactory() { + @Override + public Thread newThread(Runnable r) { + return new Thread(r, "PullMessageServiceScheduledThread"); + } + });; public PullMessageService(MQClientFactory mQClientFactory) { @@ -25,16 +52,64 @@ public PullMessageService(MQClientFactory mQClientFactory) { } + /** + * 只定时一次 + */ + public void executePullRequestLater(final PullRequest pullRequest, final long timeDelay) { + this.scheduledExecutorService.schedule(new Runnable() { + + @Override + public void run() { + PullMessageService.this.executePullRequestImmediately(pullRequest); + } + }, timeDelay, TimeUnit.MILLISECONDS); + } + + + /** + * 立刻执行PullRequest + */ + public void executePullRequestImmediately(final PullRequest pullRequest) { + try { + this.pullRequestQueue.put(pullRequest); + } + catch (InterruptedException e) { + log.error("executePullRequestImmediately pullRequestQueue.put", e); + } + } + + + private void pullMessage(final PullRequest pullRequest) { + final MQConsumerInner consumer = this.mQClientFactory.selectConsumer(pullRequest.getConsumerGroup()); + if (consumer != null) { + DefaultMQPushConsumerImpl impl = (DefaultMQPushConsumerImpl) consumer; + impl.pullMessage(pullRequest); + } + else { + log.warn("No matched consumer for the PullRequest {}, drop it", pullRequest); + } + } + + @Override public void run() { + log.info(this.getServiceName() + " service started"); + while (!this.isStoped()) { try { PullRequest pullRequest = this.pullRequestQueue.take(); + if (pullRequest != null) { + this.pullMessage(pullRequest); + } } catch (InterruptedException e) { - // TODO log + } + catch (Exception e) { + log.error("Pull Message Service Run Method exception", e); } } + + log.info(this.getServiceName() + " service end"); } @@ -42,4 +117,9 @@ public void run() { public String getServiceName() { return PullMessageService.class.getSimpleName(); } + + + public ScheduledExecutorService getScheduledExecutorService() { + return scheduledExecutorService; + } } diff --git a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/impl/consumer/PullRequest.java b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/impl/consumer/PullRequest.java index f2ad2512..2796c665 100644 --- a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/impl/consumer/PullRequest.java +++ b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/impl/consumer/PullRequest.java @@ -1,15 +1,115 @@ /** - * $Id: PullRequest.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.client.impl.consumer; +import com.alibaba.rocketmq.common.message.MessageQueue; + + /** - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * 拉消息请求 * + * @author shijia.wxr + * @since 2013-7-24 */ public class PullRequest { private String consumerGroup; - private String topic; - private int queueId; + private MessageQueue messageQueue; + private ProcessQueue processQueue; + // hashCode与equals方法不包含此字段 private long nextOffset; + + + public String getConsumerGroup() { + return consumerGroup; + } + + + public void setConsumerGroup(String consumerGroup) { + this.consumerGroup = consumerGroup; + } + + + public MessageQueue getMessageQueue() { + return messageQueue; + } + + + public void setMessageQueue(MessageQueue messageQueue) { + this.messageQueue = messageQueue; + } + + + public long getNextOffset() { + return nextOffset; + } + + + public void setNextOffset(long nextOffset) { + this.nextOffset = nextOffset; + } + + + @Override + public String toString() { + return "PullRequest [consumerGroup=" + consumerGroup + ", messageQueue=" + messageQueue + + ", nextOffset=" + nextOffset + "]"; + } + + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((consumerGroup == null) ? 0 : consumerGroup.hashCode()); + result = prime * result + ((messageQueue == null) ? 0 : messageQueue.hashCode()); + return result; + } + + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + PullRequest other = (PullRequest) obj; + if (consumerGroup == null) { + if (other.consumerGroup != null) + return false; + } + else if (!consumerGroup.equals(other.consumerGroup)) + return false; + if (messageQueue == null) { + if (other.messageQueue != null) + return false; + } + else if (!messageQueue.equals(other.messageQueue)) + return false; + return true; + } + + + public ProcessQueue getProcessQueue() { + return processQueue; + } + + + public void setProcessQueue(ProcessQueue processQueue) { + this.processQueue = processQueue; + } } diff --git a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/impl/consumer/PullResultExt.java b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/impl/consumer/PullResultExt.java index 0355bc73..a8bc35c1 100644 --- a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/impl/consumer/PullResultExt.java +++ b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/impl/consumer/PullResultExt.java @@ -1,5 +1,17 @@ /** - * $Id: PullResultExt.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.client.impl.consumer; @@ -7,34 +19,28 @@ import com.alibaba.rocketmq.client.consumer.PullResult; import com.alibaba.rocketmq.client.consumer.PullStatus; -import com.alibaba.rocketmq.common.MessageExt; +import com.alibaba.rocketmq.common.message.MessageExt; /** - * ֻڲʹã⹫ - * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * 只在内部使用,不对外公开 * + * @author shijia.wxr + * @since 2013-7-24 */ public class PullResultExt extends PullResult { - private final boolean suggestPullingFromSlave; + private final long suggestWhichBrokerId; private byte[] messageBinary; public PullResultExt(PullStatus pullStatus, long nextBeginOffset, long minOffset, long maxOffset, - List msgFoundList, final boolean suggestPullingFromSlave, - final byte[] messageBinary) { + List msgFoundList, final long suggestWhichBrokerId, final byte[] messageBinary) { super(pullStatus, nextBeginOffset, minOffset, maxOffset, msgFoundList); - this.suggestPullingFromSlave = suggestPullingFromSlave; + this.suggestWhichBrokerId = suggestWhichBrokerId; this.messageBinary = messageBinary; } - public boolean isSuggestPullingFromSlave() { - return suggestPullingFromSlave; - } - - public byte[] getMessageBinary() { return messageBinary; } @@ -43,4 +49,9 @@ public byte[] getMessageBinary() { public void setMessageBinary(byte[] messageBinary) { this.messageBinary = messageBinary; } + + + public long getSuggestWhichBrokerId() { + return suggestWhichBrokerId; + } } diff --git a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/impl/consumer/RebalanceImpl.java b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/impl/consumer/RebalanceImpl.java new file mode 100644 index 00000000..56b5dd27 --- /dev/null +++ b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/impl/consumer/RebalanceImpl.java @@ -0,0 +1,483 @@ +/** + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.rocketmq.client.impl.consumer; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; + +import org.slf4j.Logger; + +import com.alibaba.rocketmq.client.consumer.AllocateMessageQueueStrategy; +import com.alibaba.rocketmq.client.impl.FindBrokerResult; +import com.alibaba.rocketmq.client.impl.factory.MQClientFactory; +import com.alibaba.rocketmq.client.log.ClientLogger; +import com.alibaba.rocketmq.common.MixAll; +import com.alibaba.rocketmq.common.message.MessageQueue; +import com.alibaba.rocketmq.common.protocol.body.LockBatchRequestBody; +import com.alibaba.rocketmq.common.protocol.body.UnlockBatchRequestBody; +import com.alibaba.rocketmq.common.protocol.heartbeat.MessageModel; +import com.alibaba.rocketmq.common.protocol.heartbeat.SubscriptionData; + + +/** + * Rebalance的具体实现 + * + * @author shijia.wxr + * @since 2013-6-22 + */ +public abstract class RebalanceImpl { + protected static final Logger log = ClientLogger.getLog(); + // 分配好的队列,消息存储也在这里 + protected final ConcurrentHashMap processQueueTable = + new ConcurrentHashMap(64); + // 可以订阅的所有队列(定时从Name Server更新最新版本) + protected final ConcurrentHashMap> topicSubscribeInfoTable = + new ConcurrentHashMap>(); + // 订阅关系,用户配置的原始数据 + protected final ConcurrentHashMap subscriptionInner = + new ConcurrentHashMap(); + protected String consumerGroup; + protected MessageModel messageModel; + protected AllocateMessageQueueStrategy allocateMessageQueueStrategy; + protected MQClientFactory mQClientFactory; + + + public RebalanceImpl(String consumerGroup, MessageModel messageModel, + AllocateMessageQueueStrategy allocateMessageQueueStrategy, MQClientFactory mQClientFactory) { + this.consumerGroup = consumerGroup; + this.messageModel = messageModel; + this.allocateMessageQueueStrategy = allocateMessageQueueStrategy; + this.mQClientFactory = mQClientFactory; + } + + + public void unlock(final MessageQueue mq, final boolean oneway) { + FindBrokerResult findBrokerResult = + this.mQClientFactory.findBrokerAddressInSubscribe(mq.getBrokerName(), MixAll.MASTER_ID, true); + if (findBrokerResult != null) { + UnlockBatchRequestBody requestBody = new UnlockBatchRequestBody(); + requestBody.setConsumerGroup(this.consumerGroup); + requestBody.setClientId(this.mQClientFactory.getClientId()); + requestBody.getMqSet().add(mq); + + try { + this.mQClientFactory.getMQClientAPIImpl().unlockBatchMQ(findBrokerResult.getBrokerAddr(), + requestBody, 1000, oneway); + log.warn("unlock messageQueue. group:{}, clientId:{}, mq:{}",// + this.consumerGroup, // + this.mQClientFactory.getClientId(), // + mq); + } + catch (Exception e) { + log.error("unlockBatchMQ exception, " + mq, e); + } + } + } + + + public void unlockAll(final boolean oneway) { + HashMap> brokerMqs = this.buildProcessQueueTableByBrokerName(); + + for (final Map.Entry> entry : brokerMqs.entrySet()) { + final String brokerName = entry.getKey(); + final Set mqs = entry.getValue(); + + if (mqs.isEmpty()) + continue; + + FindBrokerResult findBrokerResult = + this.mQClientFactory.findBrokerAddressInSubscribe(brokerName, MixAll.MASTER_ID, true); + if (findBrokerResult != null) { + UnlockBatchRequestBody requestBody = new UnlockBatchRequestBody(); + requestBody.setConsumerGroup(this.consumerGroup); + requestBody.setClientId(this.mQClientFactory.getClientId()); + requestBody.setMqSet(mqs); + + try { + this.mQClientFactory.getMQClientAPIImpl().unlockBatchMQ(findBrokerResult.getBrokerAddr(), + requestBody, 1000, oneway); + + for (MessageQueue mq : mqs) { + ProcessQueue processQueue = this.processQueueTable.get(mq); + if (processQueue != null) { + processQueue.setLocked(false); + log.info("the message queue unlock OK, Group: {} {}", this.consumerGroup, mq); + } + } + } + catch (Exception e) { + log.error("unlockBatchMQ exception, " + mqs, e); + } + } + } + } + + + private HashMap> buildProcessQueueTableByBrokerName() { + HashMap> result = new HashMap>(); + for (MessageQueue mq : this.processQueueTable.keySet()) { + Set mqs = result.get(mq.getBrokerName()); + if (null == mqs) { + mqs = new HashSet(); + result.put(mq.getBrokerName(), mqs); + } + + mqs.add(mq); + } + + return result; + } + + + public boolean lock(final MessageQueue mq) { + FindBrokerResult findBrokerResult = + this.mQClientFactory.findBrokerAddressInSubscribe(mq.getBrokerName(), MixAll.MASTER_ID, true); + if (findBrokerResult != null) { + LockBatchRequestBody requestBody = new LockBatchRequestBody(); + requestBody.setConsumerGroup(this.consumerGroup); + requestBody.setClientId(this.mQClientFactory.getClientId()); + requestBody.getMqSet().add(mq); + + try { + Set lockedMq = + this.mQClientFactory.getMQClientAPIImpl().lockBatchMQ( + findBrokerResult.getBrokerAddr(), requestBody, 1000); + for (MessageQueue mmqq : lockedMq) { + ProcessQueue processQueue = this.processQueueTable.get(mmqq); + if (processQueue != null) { + processQueue.setLocked(true); + processQueue.setLastLockTimestamp(System.currentTimeMillis()); + } + } + + boolean lockOK = lockedMq.contains(mq); + log.info("the message queue lock {}, {} {}",// + (lockOK ? "OK" : "Failed"), // + this.consumerGroup, // + mq); + return lockOK; + } + catch (Exception e) { + log.error("lockBatchMQ exception, " + mq, e); + } + } + + return false; + } + + + public void lockAll() { + HashMap> brokerMqs = this.buildProcessQueueTableByBrokerName(); + + Iterator>> it = brokerMqs.entrySet().iterator(); + while (it.hasNext()) { + Entry> entry = it.next(); + final String brokerName = entry.getKey(); + final Set mqs = entry.getValue(); + + if (mqs.isEmpty()) + continue; + + FindBrokerResult findBrokerResult = + this.mQClientFactory.findBrokerAddressInSubscribe(brokerName, MixAll.MASTER_ID, true); + if (findBrokerResult != null) { + LockBatchRequestBody requestBody = new LockBatchRequestBody(); + requestBody.setConsumerGroup(this.consumerGroup); + requestBody.setClientId(this.mQClientFactory.getClientId()); + requestBody.setMqSet(mqs); + + try { + Set lockOKMQSet = + this.mQClientFactory.getMQClientAPIImpl().lockBatchMQ( + findBrokerResult.getBrokerAddr(), requestBody, 1000); + + // 锁定成功的队列 + for (MessageQueue mq : lockOKMQSet) { + ProcessQueue processQueue = this.processQueueTable.get(mq); + if (processQueue != null) { + if (!processQueue.isLocked()) { + log.info("the message queue locked OK, Group: {} {}", this.consumerGroup, mq); + } + + processQueue.setLocked(true); + processQueue.setLastLockTimestamp(System.currentTimeMillis()); + } + } + // 锁定失败的队列 + for (MessageQueue mq : mqs) { + if (!lockOKMQSet.contains(mq)) { + ProcessQueue processQueue = this.processQueueTable.get(mq); + if (processQueue != null) { + processQueue.setLocked(false); + log.warn("the message queue locked Failed, Group: {} {}", this.consumerGroup, + mq); + } + } + } + } + catch (Exception e) { + log.error("lockBatchMQ exception, " + mqs, e); + } + } + } + } + + + public void doRebalance() { + Map subTable = this.getSubscriptionInner(); + if (subTable != null) { + for (final Map.Entry entry : subTable.entrySet()) { + final String topic = entry.getKey(); + try { + this.rebalanceByTopic(topic); + } + catch (Exception e) { + if (!topic.startsWith(MixAll.RETRY_GROUP_TOPIC_PREFIX)) { + log.warn("rebalanceByTopic Exception", e); + } + } + } + } + + this.truncateMessageQueueNotMyTopic(); + } + + + private void rebalanceByTopic(final String topic) { + switch (messageModel) { + case BROADCASTING: { + Set mqSet = this.topicSubscribeInfoTable.get(topic); + if (mqSet != null) { + boolean changed = this.updateProcessQueueTableInRebalance(topic, mqSet); + if (changed) { + this.messageQueueChanged(topic, mqSet, mqSet); + log.info("messageQueueChanged {} {} {} {}",// + consumerGroup,// + topic,// + mqSet,// + mqSet); + } + } + else { + log.warn("doRebalance, {}, but the topic[{}] not exist.", consumerGroup, topic); + } + break; + } + case CLUSTERING: { + Set mqSet = this.topicSubscribeInfoTable.get(topic); + List cidAll = this.mQClientFactory.findConsumerIdList(topic, consumerGroup); + if (null == mqSet) { + if (!topic.startsWith(MixAll.RETRY_GROUP_TOPIC_PREFIX)) { + log.warn("doRebalance, {}, but the topic[{}] not exist.", consumerGroup, topic); + } + } + + if (null == cidAll) { + log.warn("doRebalance, {} {}, get consumer id list failed", consumerGroup, topic); + } + + if (mqSet != null && cidAll != null) { + List mqAll = new ArrayList(); + mqAll.addAll(mqSet); + + // 排序 + Collections.sort(mqAll); + Collections.sort(cidAll); + + AllocateMessageQueueStrategy strategy = this.allocateMessageQueueStrategy; + + // 执行分配算法 + List allocateResult = null; + try { + allocateResult = strategy.allocate(this.mQClientFactory.getClientId(), mqAll, cidAll); + } + catch (Throwable e) { + log.error("AllocateMessageQueueStrategy.allocate Exception", e); + } + + Set allocateResultSet = new HashSet(); + if (allocateResult != null) { + allocateResultSet.addAll(allocateResult); + } + + // 更新本地队列 + boolean changed = this.updateProcessQueueTableInRebalance(topic, allocateResultSet); + if (changed) { + log.info("rebalanced result changed. mqSet={}, ConsumerId={}, mqSize={}, cidSize={}", + allocateResult, this.mQClientFactory.getClientId(), mqAll.size(), cidAll.size()); + + this.messageQueueChanged(topic, mqSet, allocateResultSet); + log.info("messageQueueChanged {} {} {} {}",// + consumerGroup,// + topic,// + mqSet,// + allocateResultSet); + + log.info("messageQueueChanged consumerIdList: {}",// + cidAll); + } + } + break; + } + default: + break; + } + } + + + public abstract void messageQueueChanged(final String topic, final Set mqAll, + final Set mqDivided); + + + private boolean updateProcessQueueTableInRebalance(final String topic, final Set mqSet) { + boolean changed = false; + + // 将多余的队列删除 + Iterator> it = this.processQueueTable.entrySet().iterator(); + while (it.hasNext()) { + Entry next = it.next(); + MessageQueue mq = next.getKey(); + ProcessQueue pq = next.getValue(); + + if (mq.getTopic().equals(topic)) { + if (!mqSet.contains(mq)) { + changed = true; + it.remove(); + pq.setDroped(true); + log.info("doRebalance, {}, remove unnecessary mq, {}", consumerGroup, mq); + this.removeUnnecessaryMessageQueue(mq, pq); + } + } + } + + // 增加新增的队列 + List pullRequestList = new ArrayList(); + for (MessageQueue mq : mqSet) { + if (!this.processQueueTable.containsKey(mq)) { + PullRequest pullRequest = new PullRequest(); + pullRequest.setConsumerGroup(consumerGroup); + pullRequest.setMessageQueue(mq); + pullRequest.setProcessQueue(new ProcessQueue()); + + // 这个需要根据策略来设置 + long nextOffset = this.computePullFromWhere(mq); + if (nextOffset >= 0) { + pullRequest.setNextOffset(nextOffset); + pullRequestList.add(pullRequest); + changed = true; + this.processQueueTable.put(mq, pullRequest.getProcessQueue()); + log.info("doRebalance, {}, add a new mq, {}", consumerGroup, mq); + } + else { + // 等待此次Rebalance做重试 + log.warn("doRebalance, {}, add new mq failed, {}", consumerGroup, mq); + } + } + } + + this.dispatchPullRequest(pullRequestList); + + return changed; + } + + + public abstract void removeUnnecessaryMessageQueue(final MessageQueue mq, final ProcessQueue pq); + + + public abstract void dispatchPullRequest(final List pullRequestList); + + + public abstract long computePullFromWhere(final MessageQueue mq); + + + private void truncateMessageQueueNotMyTopic() { + Map subTable = this.getSubscriptionInner(); + + for (MessageQueue mq : this.processQueueTable.keySet()) { + if (!subTable.containsKey(mq.getTopic())) { + ProcessQueue pq = this.processQueueTable.remove(mq); + if (pq != null) { + pq.setDroped(true); + log.info("doRebalance, {}, truncateMessageQueueNotMyTopic remove unnecessary mq, {}", + consumerGroup, mq); + } + } + } + } + + + public ConcurrentHashMap getSubscriptionInner() { + return subscriptionInner; + } + + + public ConcurrentHashMap getProcessQueueTable() { + return processQueueTable; + } + + + public ConcurrentHashMap> getTopicSubscribeInfoTable() { + return topicSubscribeInfoTable; + } + + + public String getConsumerGroup() { + return consumerGroup; + } + + + public void setConsumerGroup(String consumerGroup) { + this.consumerGroup = consumerGroup; + } + + + public MessageModel getMessageModel() { + return messageModel; + } + + + public void setMessageModel(MessageModel messageModel) { + this.messageModel = messageModel; + } + + + public AllocateMessageQueueStrategy getAllocateMessageQueueStrategy() { + return allocateMessageQueueStrategy; + } + + + public void setAllocateMessageQueueStrategy(AllocateMessageQueueStrategy allocateMessageQueueStrategy) { + this.allocateMessageQueueStrategy = allocateMessageQueueStrategy; + } + + + public MQClientFactory getmQClientFactory() { + return mQClientFactory; + } + + + public void setmQClientFactory(MQClientFactory mQClientFactory) { + this.mQClientFactory = mQClientFactory; + } +} diff --git a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/impl/consumer/RebalancePullImpl.java b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/impl/consumer/RebalancePullImpl.java new file mode 100644 index 00000000..1155a661 --- /dev/null +++ b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/impl/consumer/RebalancePullImpl.java @@ -0,0 +1,80 @@ +/** + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.rocketmq.client.impl.consumer; + +import java.util.List; +import java.util.Set; + +import com.alibaba.rocketmq.client.consumer.AllocateMessageQueueStrategy; +import com.alibaba.rocketmq.client.consumer.MessageQueueListener; +import com.alibaba.rocketmq.client.impl.factory.MQClientFactory; +import com.alibaba.rocketmq.common.message.MessageQueue; +import com.alibaba.rocketmq.common.protocol.heartbeat.MessageModel; + + +/** + * @author shijia.wxr + * @since 2013-6-22 + */ +public class RebalancePullImpl extends RebalanceImpl { + private final DefaultMQPullConsumerImpl defaultMQPullConsumerImpl; + + + public RebalancePullImpl(DefaultMQPullConsumerImpl defaultMQPullConsumerImpl) { + this(null, null, null, null, defaultMQPullConsumerImpl); + } + + + public RebalancePullImpl(String consumerGroup, MessageModel messageModel, + AllocateMessageQueueStrategy allocateMessageQueueStrategy, MQClientFactory mQClientFactory, + DefaultMQPullConsumerImpl defaultMQPullConsumerImpl) { + super(consumerGroup, messageModel, allocateMessageQueueStrategy, mQClientFactory); + this.defaultMQPullConsumerImpl = defaultMQPullConsumerImpl; + } + + + @Override + public long computePullFromWhere(MessageQueue mq) { + return 0; + } + + + @Override + public void dispatchPullRequest(List pullRequestList) { + } + + + @Override + public void messageQueueChanged(String topic, Set mqAll, Set mqDivided) { + MessageQueueListener messageQueueListener = + this.defaultMQPullConsumerImpl.getDefaultMQPullConsumer().getMessageQueueListener(); + if (messageQueueListener != null) { + try { + messageQueueListener.messageQueueChanged(topic, mqAll, mqDivided); + } + catch (Throwable e) { + log.error("messageQueueChanged exception", e); + } + } + } + + + @Override + public void removeUnnecessaryMessageQueue(MessageQueue mq, ProcessQueue pq) { + this.defaultMQPullConsumerImpl.getOffsetStore().persist(mq); + this.defaultMQPullConsumerImpl.getOffsetStore().removeOffset(mq); + } +} diff --git a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/impl/consumer/RebalancePushImpl.java b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/impl/consumer/RebalancePushImpl.java new file mode 100644 index 00000000..bb01ee01 --- /dev/null +++ b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/impl/consumer/RebalancePushImpl.java @@ -0,0 +1,180 @@ +/** + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.rocketmq.client.impl.consumer; + +import java.util.List; +import java.util.Set; + +import com.alibaba.rocketmq.client.consumer.AllocateMessageQueueStrategy; +import com.alibaba.rocketmq.client.consumer.store.OffsetStore; +import com.alibaba.rocketmq.client.consumer.store.ReadOffsetType; +import com.alibaba.rocketmq.client.exception.MQClientException; +import com.alibaba.rocketmq.client.impl.factory.MQClientFactory; +import com.alibaba.rocketmq.common.MixAll; +import com.alibaba.rocketmq.common.UtilAll; +import com.alibaba.rocketmq.common.consumer.ConsumeFromWhere; +import com.alibaba.rocketmq.common.message.MessageQueue; +import com.alibaba.rocketmq.common.protocol.heartbeat.MessageModel; + + +/** + * @author shijia.wxr + * @since 2013-6-22 + */ +public class RebalancePushImpl extends RebalanceImpl { + private final DefaultMQPushConsumerImpl defaultMQPushConsumerImpl; + + + public RebalancePushImpl(DefaultMQPushConsumerImpl defaultMQPushConsumerImpl) { + this(null, null, null, null, defaultMQPushConsumerImpl); + } + + + public RebalancePushImpl(String consumerGroup, MessageModel messageModel, + AllocateMessageQueueStrategy allocateMessageQueueStrategy, MQClientFactory mQClientFactory, + DefaultMQPushConsumerImpl defaultMQPushConsumerImpl) { + super(consumerGroup, messageModel, allocateMessageQueueStrategy, mQClientFactory); + this.defaultMQPushConsumerImpl = defaultMQPushConsumerImpl; + } + + + @Override + public void dispatchPullRequest(List pullRequestList) { + // 派发PullRequest + for (PullRequest pullRequest : pullRequestList) { + this.defaultMQPushConsumerImpl.executePullRequestImmediately(pullRequest); + log.info("doRebalance, {}, add a new pull request {}", consumerGroup, pullRequest); + } + } + + + @Override + public long computePullFromWhere(MessageQueue mq) { + // 如果返回-1,这个队列的rebalance会失败重试,但是不影响其他队列。 + long result = -1; + final ConsumeFromWhere consumeFromWhere = + this.defaultMQPushConsumerImpl.getDefaultMQPushConsumer().getConsumeFromWhere(); + final OffsetStore offsetStore = this.defaultMQPushConsumerImpl.getOffsetStore(); + switch (consumeFromWhere) { + case CONSUME_FROM_LAST_OFFSET_AND_FROM_MIN_WHEN_BOOT_FIRST: + case CONSUME_FROM_MIN_OFFSET: + case CONSUME_FROM_MAX_OFFSET: + case CONSUME_FROM_LAST_OFFSET: { + long lastOffset = offsetStore.readOffset(mq, ReadOffsetType.READ_FROM_STORE); + // 第二次启动,根据上次的消费位点开始消费 + if (lastOffset >= 0) { + result = lastOffset; + } + // 第一次启动,没有记录消费位点 + else if (-1 == lastOffset) { + // 重试队列则从队列头部开始 + if (mq.getTopic().startsWith(MixAll.RETRY_GROUP_TOPIC_PREFIX)) { + result = 0L; + } + // 正常队列则从队列尾部开始 + else { + try { + result = this.mQClientFactory.getMQAdminImpl().maxOffset(mq); + } + catch (MQClientException e) { + result = -1; + } + } + } + // 其他错误 + else { + result = -1; + } + break; + } + case CONSUME_FROM_FIRST_OFFSET: { + long lastOffset = offsetStore.readOffset(mq, ReadOffsetType.READ_FROM_STORE); + // 第二次启动,根据上次的消费位点开始消费 + if (lastOffset >= 0) { + result = lastOffset; + } + // 第一次启动,没有记录消费位点 + else if (-1 == lastOffset) { + result = 0L; + } + // 其他错误 + else { + result = -1; + } + break; + } + case CONSUME_FROM_TIMESTAMP: { + long lastOffset = offsetStore.readOffset(mq, ReadOffsetType.READ_FROM_STORE); + // 第二次启动,根据上次的消费位点开始消费 + if (lastOffset >= 0) { + result = lastOffset; + } + // 第一次启动,没有记录消费为点 + else if (-1 == lastOffset) { + // 重试队列则从队列尾部开始 + if (mq.getTopic().startsWith(MixAll.RETRY_GROUP_TOPIC_PREFIX)) { + try { + result = this.mQClientFactory.getMQAdminImpl().maxOffset(mq); + } + catch (MQClientException e) { + result = -1; + } + } + // 正常队列则从指定时间点开始 + else { + try { + // 时间点需要参数配置 + long timestamp = + UtilAll.parseDate( + this.defaultMQPushConsumerImpl.getDefaultMQPushConsumer() + .getConsumeTimestamp(), UtilAll.yyyyMMddHHmmss).getTime(); + result = this.mQClientFactory.getMQAdminImpl().searchOffset(mq, timestamp); + } + catch (MQClientException e) { + result = -1; + } + } + } + // 其他错误 + else { + result = -1; + } + break; + } + + default: + break; + } + + return result; + } + + + @Override + public void messageQueueChanged(String topic, Set mqAll, Set mqDivided) { + } + + + @Override + public void removeUnnecessaryMessageQueue(MessageQueue mq, ProcessQueue pq) { + this.defaultMQPushConsumerImpl.getOffsetStore().persist(mq); + this.defaultMQPushConsumerImpl.getOffsetStore().removeOffset(mq); + if (this.defaultMQPushConsumerImpl.isConsumeOrderly() + && MessageModel.CLUSTERING.equals(this.defaultMQPushConsumerImpl.messageModel())) { + this.unlock(mq, true); + } + } +} diff --git a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/impl/consumer/RebalanceService.java b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/impl/consumer/RebalanceService.java new file mode 100644 index 00000000..7413fcb9 --- /dev/null +++ b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/impl/consumer/RebalanceService.java @@ -0,0 +1,60 @@ +/** + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.rocketmq.client.impl.consumer; + +import org.slf4j.Logger; + +import com.alibaba.rocketmq.client.impl.factory.MQClientFactory; +import com.alibaba.rocketmq.client.log.ClientLogger; +import com.alibaba.rocketmq.common.ServiceThread; + + +/** + * Rebalance服务 + * + * @author shijia.wxr + * @since 2013-7-24 + */ +public class RebalanceService extends ServiceThread { + private final Logger log = ClientLogger.getLog(); + private final MQClientFactory mqClientFactory; + + + public RebalanceService(MQClientFactory mqClientFactory) { + this.mqClientFactory = mqClientFactory; + } + + private static long WaitInterval = 1000 * 10; + + + @Override + public void run() { + log.info(this.getServiceName() + " service started"); + + while (!this.isStoped()) { + this.waitForRunning(WaitInterval); + this.mqClientFactory.doRebalance(); + } + + log.info(this.getServiceName() + " service end"); + } + + + @Override + public String getServiceName() { + return RebalanceService.class.getSimpleName(); + } +} diff --git a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/impl/factory/MQClientFactory.java b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/impl/factory/MQClientFactory.java index bd4dc92a..ac1cdc19 100644 --- a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/impl/factory/MQClientFactory.java +++ b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/impl/factory/MQClientFactory.java @@ -1,14 +1,29 @@ /** - * $Id: MQClientFactory.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.client.impl.factory; -import java.util.ArrayList; +import java.net.DatagramSocket; +import java.net.SocketException; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; +import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.Map.Entry; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.Executors; @@ -20,20 +35,31 @@ import org.slf4j.Logger; -import com.alibaba.rocketmq.client.MQClientConfig; -import com.alibaba.rocketmq.client.consumer.ConsumeFromWhichNode; +import com.alibaba.rocketmq.client.ClientConfig; +import com.alibaba.rocketmq.client.admin.MQAdminExtInner; import com.alibaba.rocketmq.client.exception.MQBrokerException; import com.alibaba.rocketmq.client.exception.MQClientException; import com.alibaba.rocketmq.client.impl.ClientRemotingProcessor; import com.alibaba.rocketmq.client.impl.FindBrokerResult; import com.alibaba.rocketmq.client.impl.MQAdminImpl; import com.alibaba.rocketmq.client.impl.MQClientAPIImpl; +import com.alibaba.rocketmq.client.impl.MQClientManager; +import com.alibaba.rocketmq.client.impl.consumer.DefaultMQPullConsumerImpl; +import com.alibaba.rocketmq.client.impl.consumer.DefaultMQPushConsumerImpl; import com.alibaba.rocketmq.client.impl.consumer.MQConsumerInner; +import com.alibaba.rocketmq.client.impl.consumer.ProcessQueue; +import com.alibaba.rocketmq.client.impl.consumer.PullMessageService; +import com.alibaba.rocketmq.client.impl.consumer.RebalanceService; import com.alibaba.rocketmq.client.impl.producer.DefaultMQProducerImpl; +import com.alibaba.rocketmq.client.impl.producer.MQProducerInner; import com.alibaba.rocketmq.client.impl.producer.TopicPublishInfo; +import com.alibaba.rocketmq.client.log.ClientLogger; +import com.alibaba.rocketmq.client.producer.DefaultMQProducer; import com.alibaba.rocketmq.common.MixAll; -import com.alibaba.rocketmq.common.MessageQueue; import com.alibaba.rocketmq.common.ServiceState; +import com.alibaba.rocketmq.common.constant.PermName; +import com.alibaba.rocketmq.common.help.FAQUrl; +import com.alibaba.rocketmq.common.message.MessageQueue; import com.alibaba.rocketmq.common.protocol.heartbeat.ConsumerData; import com.alibaba.rocketmq.common.protocol.heartbeat.HeartbeatData; import com.alibaba.rocketmq.common.protocol.heartbeat.ProducerData; @@ -43,47 +69,46 @@ import com.alibaba.rocketmq.common.protocol.route.TopicRouteData; import com.alibaba.rocketmq.remoting.exception.RemotingException; import com.alibaba.rocketmq.remoting.netty.NettyClientConfig; -import com.google.protobuf.InvalidProtocolBufferException; /** - * ͻFactory࣬ProducerConsumer - * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * 客户端Factory类,用来管理Producer与Consumer * + * @author shijia.wxr + * @since 2013-6-15 */ public class MQClientFactory { - private ServiceState serviceState = ServiceState.CREATE_JUST; - private final Logger log; - private final MQClientConfig mQClientConfig; + private final static long LockTimeoutMillis = 3000; + private final Logger log = ClientLogger.getLog(); + private final ClientConfig clientConfig; private final int factoryIndex; private final String clientId; private final long bootTimestamp = System.currentTimeMillis(); - - // Producer - private final ConcurrentHashMap producerTable = - new ConcurrentHashMap(); - // Consumer + // Producer对象 + private final ConcurrentHashMap producerTable = + new ConcurrentHashMap(); + // Consumer对象 private final ConcurrentHashMap consumerTable = new ConcurrentHashMap(); - // Nettyͻ + // AdminExt对象 + private final ConcurrentHashMap adminExtTable = + new ConcurrentHashMap(); + // Netty客户端配置 private final NettyClientConfig nettyClientConfig; - // RPCõķװ + // RPC调用的封装类 private final MQClientAPIImpl mQClientAPIImpl; private final MQAdminImpl mQAdminImpl; - - // 洢Name ServerõTopic·Ϣ + // 存储从Name Server拿到的Topic路由信息 private final ConcurrentHashMap topicRouteTable = new ConcurrentHashMap(); - // Name ServerȡTopic·Ϣʱ + // 调用Name Server获取Topic路由信息时,加锁 private final Lock lockNamesrv = new ReentrantLock(); - private final static long LockTimeoutMillis = 3000; - - // 洢Broker Name Broker AddressĶӦϵ + // 心跳与注销动作加锁 + private final Lock lockHeartbeat = new ReentrantLock(); + // 存储Broker Name 与Broker Address的对应关系 private final ConcurrentHashMap> brokerAddrTable = new ConcurrentHashMap>(); - - // ʱ߳ + // 定时线程 private final ScheduledExecutorService scheduledExecutorService = Executors .newSingleThreadScheduledExecutor(new ThreadFactory() { @Override @@ -91,51 +116,109 @@ public Thread newThread(Runnable r) { return new Thread(r, "MQClientFactoryScheduledThread"); } }); - + // 处理服务器主动发来的请求 private final ClientRemotingProcessor clientRemotingProcessor; + // 拉消息服务 + private final PullMessageService pullMessageService; + // Rebalance服务 + private final RebalanceService rebalanceService; + // 内置Producer对象 + private final DefaultMQProducer defaultMQProducer; + private ServiceState serviceState = ServiceState.CREATE_JUST; + // 监听一个UDP端口,用来防止同一个Factory启动多份(有可能分布在多个JVM中) + private DatagramSocket datagramSocket; - public MQClientFactory(MQClientConfig mQClientConfig, int factoryIndex) { - this.mQClientConfig = mQClientConfig; - this.log = MixAll.createLogger(mQClientConfig.getLogFileName(), mQClientConfig.getLogLevel()); + public MQClientFactory(ClientConfig clientConfig, int factoryIndex, String clientId) { + this.clientConfig = clientConfig; this.factoryIndex = factoryIndex; this.nettyClientConfig = new NettyClientConfig(); - this.nettyClientConfig.setClientCallbackExecutorThreads(mQClientConfig.getClientCallbackExecutorThreads()); - this.clientRemotingProcessor = new ClientRemotingProcessor(this, this.log); + this.nettyClientConfig.setClientCallbackExecutorThreads(clientConfig + .getClientCallbackExecutorThreads()); + this.clientRemotingProcessor = new ClientRemotingProcessor(this); this.mQClientAPIImpl = new MQClientAPIImpl(this.nettyClientConfig, this.clientRemotingProcessor); - if (this.mQClientConfig.getNamesrvAddr() != null) { - this.mQClientAPIImpl.updateNameServerAddressList(this.mQClientConfig.getNamesrvAddr()); - log.info("user specfied name server address: {}", this.mQClientConfig.getNamesrvAddr()); + if (this.clientConfig.getNamesrvAddr() != null) { + this.mQClientAPIImpl.updateNameServerAddressList(this.clientConfig.getNamesrvAddr()); + log.info("user specfied name server address: {}", this.clientConfig.getNamesrvAddr()); } - this.clientId = this.buildMQClientId(); + this.clientId = clientId; this.mQAdminImpl = new MQAdminImpl(this); - log.info("created a new client fatory, ", this.factoryIndex); + this.pullMessageService = new PullMessageService(this); + + this.rebalanceService = new RebalanceService(this); + + this.defaultMQProducer = new DefaultMQProducer(MixAll.CLIENT_INNER_PRODUCER_GROUP); + this.defaultMQProducer.resetClientConfig(clientConfig); + + log.info("created a new client fatory, FactoryIndex: {} ClinetID: {} {}",// + this.factoryIndex, // + this.clientId, // + this.clientConfig); } - private String buildMQClientId() { - StringBuilder sb = new StringBuilder(); - sb.append(this.mQClientConfig.getClientIP()); - sb.append("@"); + public void start() throws MQClientException { + synchronized (this) { + switch (this.serviceState) { + case CREATE_JUST: + this.makesureInstanceNameIsOnly(this.clientConfig.getInstanceName()); - sb.append(this.mQClientConfig.getInstanceName()); - sb.append("@"); + this.serviceState = ServiceState.START_FAILED; + if (null == this.clientConfig.getNamesrvAddr()) { + this.clientConfig.setNamesrvAddr(this.mQClientAPIImpl.fetchNameServerAddr()); + } - sb.append(MixAll.CURRENT_JVM_PID); - sb.append("@"); + this.mQClientAPIImpl.start(); + this.startScheduledTask(); + this.pullMessageService.start(); + this.rebalanceService.start(); - sb.append(this.bootTimestamp); - return sb.toString(); + this.defaultMQProducer.getDefaultMQProducerImpl().start(false); + log.info("the client factory [{}] start OK", this.clientId); + this.serviceState = ServiceState.RUNNING; + break; + case RUNNING: + break; + case SHUTDOWN_ALREADY: + break; + case START_FAILED: + throw new MQClientException("The Factory object[" + this.getClientId() + + "] has been created before, and failed.", null); + default: + break; + } + } + } + + + private void makesureInstanceNameIsOnly(final String instanceName) throws MQClientException { + int udpPort = 33333; + + int value = instanceName.hashCode(); + if (value < 0) { + value = Math.abs(value); + } + + udpPort += value % 10000; + + try { + this.datagramSocket = new DatagramSocket(udpPort); + } + catch (SocketException e) { + throw new MQClientException("instance name is a duplicate one[" + instanceName + "," + udpPort + + "], please set a new name" + + FAQUrl.suggestTodo(FAQUrl.CLIENT_INSTACNCE_NAME_DUPLICATE_URL), e); + } } private void startScheduledTask() { - // ʱȡName Serverַ - if (null == this.mQClientConfig.getNamesrvAddr()) { + // 定时获取Name Server地址 + if (null == this.clientConfig.getNamesrvAddr()) { this.scheduledExecutorService.scheduleAtFixedRate(new Runnable() { @Override @@ -150,7 +233,7 @@ public void run() { }, 1000 * 10, 1000 * 60 * 2, TimeUnit.MILLISECONDS); } - // ʱName ServerȡTopic·Ϣ + // 定时从Name Server获取Topic路由信息 this.scheduledExecutorService.scheduleAtFixedRate(new Runnable() { @Override @@ -162,66 +245,574 @@ public void run() { log.error("ScheduledTask updateTopicRouteInfoFromNameServer exception", e); } } - }, 0, this.mQClientConfig.getPollNameServerInteval(), TimeUnit.MILLISECONDS); + }, 10, this.clientConfig.getPollNameServerInteval(), TimeUnit.MILLISECONDS); - // BrokerϢĹϵȣ + // 定时清理下线的Broker + // 向所有Broker发送心跳信息(包含订阅关系等) this.scheduledExecutorService.scheduleAtFixedRate(new Runnable() { @Override public void run() { try { - MQClientFactory.this.sendHeartbeatToAllBroker(); + MQClientFactory.this.cleanOfflineBroker(); + MQClientFactory.this.sendHeartbeatToAllBrokerWithLock(); } catch (Exception e) { log.error("ScheduledTask sendHeartbeatToAllBroker exception", e); } } - }, 1000, this.mQClientConfig.getHeartbeatBrokerInterval(), TimeUnit.MILLISECONDS); + }, 1000, this.clientConfig.getHeartbeatBrokerInterval(), TimeUnit.MILLISECONDS); + + // 定时持久化Consumer消费进度(广播存储到本地,集群存储到Broker) + this.scheduledExecutorService.scheduleAtFixedRate(new Runnable() { + + @Override + public void run() { + try { + MQClientFactory.this.persistAllConsumerOffset(); + } + catch (Exception e) { + log.error("ScheduledTask persistAllConsumerOffset exception", e); + } + } + }, 1000 * 10, this.clientConfig.getPersistConsumerOffsetInterval(), TimeUnit.MILLISECONDS); + + // 统计信息打点 + this.scheduledExecutorService.scheduleAtFixedRate(new Runnable() { + + @Override + public void run() { + try { + MQClientFactory.this.recordSnapshotPeriodically(); + } + catch (Exception e) { + log.error("ScheduledTask uploadConsumerOffsets exception", e); + } + } + }, 1000 * 10, 1000, TimeUnit.MILLISECONDS); + + this.scheduledExecutorService.scheduleAtFixedRate(new Runnable() { + + @Override + public void run() { + try { + MQClientFactory.this.logStatsPeriodically(); + } + catch (Exception e) { + log.error("ScheduledTask uploadConsumerOffsets exception", e); + } + } + }, 1000 * 10, 1000 * 60, TimeUnit.MILLISECONDS); } - public void start() { - synchronized (this) { - switch (this.serviceState) { - case CREATE_JUST: - this.serviceState = ServiceState.RUNNING; - // TODO - if (null == this.mQClientConfig.getNamesrvAddr()) { - MQClientFactory.this.mQClientAPIImpl.fetchNameServerAddr(); + /** + * 清理下线的broker + */ + private void cleanOfflineBroker() { + try { + if (this.lockNamesrv.tryLock(LockTimeoutMillis, TimeUnit.MILLISECONDS)) + try { + ConcurrentHashMap> updatedTable = + new ConcurrentHashMap>(); + + Iterator>> itBrokerTable = + this.brokerAddrTable.entrySet().iterator(); + while (itBrokerTable.hasNext()) { + Entry> entry = itBrokerTable.next(); + String brokerName = entry.getKey(); + HashMap oneTable = entry.getValue(); + + HashMap cloneAddrTable = new HashMap(); + cloneAddrTable.putAll(oneTable); + + Iterator> it = cloneAddrTable.entrySet().iterator(); + while (it.hasNext()) { + Entry ee = it.next(); + String addr = ee.getValue(); + if (!this.isBrokerAddrExistInTopicRouteTable(addr)) { + it.remove(); + log.info("the broker addr[{} {}] is offline, remove it", brokerName, addr); + } + } + + if (cloneAddrTable.isEmpty()) { + itBrokerTable.remove(); + log.info("the broker[{}] name's host is offline, remove it", brokerName); + } + else { + updatedTable.put(brokerName, cloneAddrTable); + } + } + + if (!updatedTable.isEmpty()) { + this.brokerAddrTable.putAll(updatedTable); + } } + finally { + this.lockNamesrv.unlock(); + } + } + catch (InterruptedException e) { + log.warn("cleanOfflineBroker Exception", e); + } + } - this.startScheduledTask(); - this.mQClientAPIImpl.start(); - break; - case RUNNING: - break; - case SHUTDOWN_ALREADY: - break; - default: - break; + + private boolean isBrokerAddrExistInTopicRouteTable(final String addr) { + Iterator> it = this.topicRouteTable.entrySet().iterator(); + while (it.hasNext()) { + Entry entry = it.next(); + TopicRouteData topicRouteData = entry.getValue(); + List bds = topicRouteData.getBrokerDatas(); + for (BrokerData bd : bds) { + if (bd.getBrokerAddrs() != null) { + boolean exist = bd.getBrokerAddrs().containsValue(addr); + if (exist) + return true; + } + } + } + + return false; + } + + + private void recordSnapshotPeriodically() { + Iterator> it = this.consumerTable.entrySet().iterator(); + while (it.hasNext()) { + Entry entry = it.next(); + MQConsumerInner impl = entry.getValue(); + if (impl != null) { + if (impl instanceof DefaultMQPushConsumerImpl) { + DefaultMQPushConsumerImpl consumer = (DefaultMQPushConsumerImpl) impl; + consumer.getConsumerStatManager().recordSnapshotPeriodically(); + } + } + } + } + + + private void logStatsPeriodically() { + Iterator> it = this.consumerTable.entrySet().iterator(); + while (it.hasNext()) { + Entry entry = it.next(); + MQConsumerInner impl = entry.getValue(); + if (impl != null) { + if (impl instanceof DefaultMQPushConsumerImpl) { + DefaultMQPushConsumerImpl consumer = (DefaultMQPushConsumerImpl) impl; + consumer.getConsumerStatManager().logStatsPeriodically(entry.getKey(), this.clientId); + } + } + } + } + + + private void persistAllConsumerOffset() { + Iterator> it = this.consumerTable.entrySet().iterator(); + while (it.hasNext()) { + Entry entry = it.next(); + MQConsumerInner impl = entry.getValue(); + impl.persistConsumerOffset(); + } + } + + + public void sendHeartbeatToAllBrokerWithLock() { + if (this.lockHeartbeat.tryLock()) { + try { + this.sendHeartbeatToAllBroker(); + } + catch (final Exception e) { + log.error("sendHeartbeatToAllBroker exception", e); + } + finally { + this.lockHeartbeat.unlock(); + } + } + else { + log.warn("lock heartBeat, but failed."); + } + } + + + private void sendHeartbeatToAllBroker() { + final HeartbeatData heartbeatData = this.prepareHeartbeatData(); + final boolean producerEmpty = heartbeatData.getProducerDataSet().isEmpty(); + final boolean consumerEmpty = heartbeatData.getConsumerDataSet().isEmpty(); + if (producerEmpty && consumerEmpty) { + log.warn("sending hearbeat, but no consumer and no producer"); + return; + } + + Iterator>> it = this.brokerAddrTable.entrySet().iterator(); + while (it.hasNext()) { + Entry> entry = it.next(); + String brokerName = entry.getKey(); + HashMap oneTable = entry.getValue(); + if (oneTable != null) { + for (Long id : oneTable.keySet()) { + String addr = oneTable.get(id); + if (addr != null) { + // 说明只有Producer,则不向Slave发心跳 + if (consumerEmpty) { + if (id != MixAll.MASTER_ID) + continue; + } + + try { + this.mQClientAPIImpl.sendHearbeat(addr, heartbeatData, 3000); + log.info("send heart beat to broker[{} {} {}] success", brokerName, id, addr); + log.info(heartbeatData.toString()); + } + catch (Exception e) { + log.error("send heart beat to broker exception", e); + } + } + } + } + } + } + + + private HeartbeatData prepareHeartbeatData() { + HeartbeatData heartbeatData = new HeartbeatData(); + + // clientID + heartbeatData.setClientID(this.clientId); + + // Consumer + for (String group : this.consumerTable.keySet()) { + MQConsumerInner impl = this.consumerTable.get(group); + if (impl != null) { + ConsumerData consumerData = new ConsumerData(); + consumerData.setGroupName(impl.groupName()); + consumerData.setConsumeType(impl.consumeType()); + consumerData.setMessageModel(impl.messageModel()); + consumerData.setConsumeFromWhere(impl.consumeFromWhere()); + consumerData.getSubscriptionDataSet().addAll(impl.subscriptions()); + + heartbeatData.getConsumerDataSet().add(consumerData); + } + } + + // Producer + for (String group : this.producerTable.keySet()) { + MQProducerInner impl = this.producerTable.get(group); + if (impl != null) { + ProducerData producerData = new ProducerData(); + producerData.setGroupName(group); + + heartbeatData.getProducerDataSet().add(producerData); + } + } + + return heartbeatData; + } + + + public void updateTopicRouteInfoFromNameServer() { + Set topicList = new HashSet(); + + // Consumer对象 + { + Iterator> it = this.consumerTable.entrySet().iterator(); + while (it.hasNext()) { + Entry entry = it.next(); + MQConsumerInner impl = entry.getValue(); + if (impl != null) { + Set subList = impl.subscriptions(); + if (subList != null) { + for (SubscriptionData subData : subList) { + topicList.add(subData.getTopic()); + } + } + } + } + } + + // Producer + { + Iterator> it = this.producerTable.entrySet().iterator(); + while (it.hasNext()) { + Entry entry = it.next(); + MQProducerInner impl = entry.getValue(); + if (impl != null) { + Set lst = impl.getPublishTopicList(); + topicList.addAll(lst); + } + } + } + + for (String topic : topicList) { + this.updateTopicRouteInfoFromNameServer(topic); + } + } + + + public boolean updateTopicRouteInfoFromNameServer(final String topic) { + return updateTopicRouteInfoFromNameServer(topic, false, null); + } + + + /** + * 调用Name Server接口,根据Topic获取路由信息 + */ + public boolean updateTopicRouteInfoFromNameServer(final String topic, boolean isDefault, + DefaultMQProducer defaultMQProducer) { + try { + if (this.lockNamesrv.tryLock(LockTimeoutMillis, TimeUnit.MILLISECONDS)) { + try { + TopicRouteData topicRouteData; + if (isDefault && defaultMQProducer != null) { + topicRouteData = + this.mQClientAPIImpl.getDefaultTopicRouteInfoFromNameServer( + defaultMQProducer.getCreateTopicKey(), 1000 * 3); + if (topicRouteData != null) { + for (QueueData data : topicRouteData.getQueueDatas()) { + // 读写分区个数是一致,故只做一次判断 + int queueNums = + Math.min(defaultMQProducer.getDefaultTopicQueueNums(), + data.getReadQueueNums()); + data.setReadQueueNums(queueNums); + data.setWriteQueueNums(queueNums); + } + } + } + else { + topicRouteData = + this.mQClientAPIImpl.getTopicRouteInfoFromNameServer(topic, 1000 * 3); + } + if (topicRouteData != null) { + TopicRouteData old = this.topicRouteTable.get(topic); + boolean changed = topicRouteDataIsChange(old, topicRouteData); + if (!changed) { + changed = this.isNeedUpdateTopicRouteInfo(topic); + } + else { + log.info("the topic[{}] route info changed, odl[{}] ,new[{}]", topic, old, + topicRouteData); + } + + if (changed) { + // 后面排序会影响下次的equal逻辑判断,所以先clone一份 + TopicRouteData cloneTopicRouteData = topicRouteData.cloneTopicRouteData(); + + // 更新Broker地址信息 + for (BrokerData bd : topicRouteData.getBrokerDatas()) { + this.brokerAddrTable.put(bd.getBrokerName(), bd.getBrokerAddrs()); + } + + // 更新发布队列信息 + { + TopicPublishInfo publishInfo = + topicRouteData2TopicPublishInfo(topic, topicRouteData); + Iterator> it = + this.producerTable.entrySet().iterator(); + while (it.hasNext()) { + Entry entry = it.next(); + MQProducerInner impl = entry.getValue(); + if (impl != null) { + impl.updateTopicPublishInfo(topic, publishInfo); + } + } + } + + // 更新订阅队列信息 + { + Set subscribeInfo = + topicRouteData2TopicSubscribeInfo(topic, topicRouteData); + Iterator> it = + this.consumerTable.entrySet().iterator(); + while (it.hasNext()) { + Entry entry = it.next(); + MQConsumerInner impl = entry.getValue(); + if (impl != null) { + impl.updateTopicSubscribeInfo(topic, subscribeInfo); + } + } + } + log.info("topicRouteTable.put TopicRouteData[{}]", cloneTopicRouteData); + this.topicRouteTable.put(topic, cloneTopicRouteData); + return true; + } + } + else { + log.warn( + "updateTopicRouteInfoFromNameServer, getTopicRouteInfoFromNameServer return null, Topic: {}", + topic); + } + } + catch (Exception e) { + if (!topic.startsWith(MixAll.RETRY_GROUP_TOPIC_PREFIX) + && !topic.equals(MixAll.DEFAULT_TOPIC)) { + log.warn("updateTopicRouteInfoFromNameServer Exception", e); + } + } + finally { + this.lockNamesrv.unlock(); + } + } + else { + log.warn("updateTopicRouteInfoFromNameServer tryLock timeout {}ms", LockTimeoutMillis); + } + } + catch (InterruptedException e) { + log.warn("updateTopicRouteInfoFromNameServer Exception", e); + } + + return false; + } + + + private boolean topicRouteDataIsChange(TopicRouteData olddata, TopicRouteData nowdata) { + if (olddata == null || nowdata == null) + return true; + TopicRouteData old = olddata.cloneTopicRouteData(); + TopicRouteData now = nowdata.cloneTopicRouteData(); + Collections.sort(old.getQueueDatas()); + Collections.sort(old.getBrokerDatas()); + Collections.sort(now.getQueueDatas()); + Collections.sort(now.getBrokerDatas()); + return !old.equals(now); + + } + + + public static TopicPublishInfo topicRouteData2TopicPublishInfo(final String topic, + final TopicRouteData route) { + TopicPublishInfo info = new TopicPublishInfo(); + // 顺序消息 + if (route.getOrderTopicConf() != null && route.getOrderTopicConf().length() > 0) { + String[] brokers = route.getOrderTopicConf().split(";"); + for (String broker : brokers) { + String[] item = broker.split(":"); + int nums = Integer.parseInt(item[1]); + for (int i = 0; i < nums; i++) { + MessageQueue mq = new MessageQueue(topic, item[0], i); + info.getMessageQueueList().add(mq); + } + } + + info.setOrderTopic(true); + } + // 非顺序消息 + else { + List qds = route.getQueueDatas(); + // 排序原因:即使没有配置顺序消息模式,默认队列的顺序同配置的一致。 + Collections.sort(qds); + for (QueueData qd : qds) { + if (PermName.isWriteable(qd.getPerm())) { + // 这里需要判断BrokerName对应的Master是否存在,因为只能向Master发送消息 + BrokerData brokerData = null; + for (BrokerData bd : route.getBrokerDatas()) { + if (bd.getBrokerName().equals(qd.getBrokerName())) { + brokerData = bd; + break; + } + } + + if (null == brokerData) { + continue; + } + + if (!brokerData.getBrokerAddrs().containsKey(MixAll.MASTER_ID)) { + continue; + } + + for (int i = 0; i < qd.getWriteQueueNums(); i++) { + MessageQueue mq = new MessageQueue(topic, qd.getBrokerName(), i); + info.getMessageQueueList().add(mq); + } + } + } + + info.setOrderTopic(false); + } + + return info; + } + + + public static Set topicRouteData2TopicSubscribeInfo(final String topic, + final TopicRouteData route) { + Set mqList = new HashSet(); + List qds = route.getQueueDatas(); + for (QueueData qd : qds) { + if (PermName.isReadable(qd.getPerm())) { + for (int i = 0; i < qd.getReadQueueNums(); i++) { + MessageQueue mq = new MessageQueue(topic, qd.getBrokerName(), i); + mqList.add(mq); + } + } + } + + return mqList; + } + + + private boolean isNeedUpdateTopicRouteInfo(final String topic) { + boolean result = false; + // 查看发布队列是否需要更新 + { + Iterator> it = this.producerTable.entrySet().iterator(); + while (it.hasNext() && !result) { + Entry entry = it.next(); + MQProducerInner impl = entry.getValue(); + if (impl != null) { + result = impl.isPublishTopicNeedUpdate(topic); + } + } + } + + // 查看订阅队列是否需要更新 + { + Iterator> it = this.consumerTable.entrySet().iterator(); + while (it.hasNext() && !result) { + Entry entry = it.next(); + MQConsumerInner impl = entry.getValue(); + if (impl != null) { + result = impl.isSubscribeTopicNeedUpdate(topic); + } } } + + return result; } public void shutdown() { - // Producer - if (!this.producerTable.isEmpty()) - return; - // Consumer if (!this.consumerTable.isEmpty()) return; + // AdminExt + if (!this.adminExtTable.isEmpty()) + return; + + // Producer + if (this.producerTable.size() > 1) + return; + synchronized (this) { switch (this.serviceState) { case CREATE_JUST: break; case RUNNING: + this.defaultMQProducer.getDefaultMQProducerImpl().shutdown(false); + this.serviceState = ServiceState.SHUTDOWN_ALREADY; - // TODO + this.pullMessageService.shutdown(true); this.scheduledExecutorService.shutdown(); this.mQClientAPIImpl.shutdown(); + this.rebalanceService.shutdown(); + + if (this.datagramSocket != null) { + this.datagramSocket.close(); + this.datagramSocket = null; + } + MQClientManager.getInstance().removeClientFactory(this.clientId); + log.info("the client factory [{}] shutdown OK", this.clientId); break; case SHUTDOWN_ALREADY: break; @@ -232,104 +823,76 @@ public void shutdown() { } - private void unregisterClient(final String producerGroup, final String consumerGroup) { - for (String name : this.brokerAddrTable.keySet()) { - final HashMap oneTable = this.brokerAddrTable.get(name); - if (oneTable != null) { - for (Long id : oneTable.keySet()) { - String addr = oneTable.get(id); - if (addr != null) { - try { - this.mQClientAPIImpl.unregisterClient(addr, this.clientId, producerGroup, - consumerGroup, 3000); - log.info("unregister client[Producer: {} Consumer: {}] from broker[{} {} {}] success", - producerGroup, consumerGroup, name, id, addr); - } - catch (RemotingException e) { - log.error("unregister client exception from broker: " + addr, e); - } - catch (MQBrokerException e) { - log.error("unregister client exception from broker: " + addr, e); - } - catch (InterruptedException e) { - log.error("unregister client exception from broker: " + addr, e); - } - } - } - } + public boolean registerConsumer(final String group, final MQConsumerInner consumer) { + if (null == group || null == consumer) { + return false; } - } + MQConsumerInner prev = this.consumerTable.putIfAbsent(group, consumer); + if (prev != null) { + log.warn("the consumer group[" + group + "] exist already."); + return false; + } - private HeartbeatData prepareHeartbeatData() { - HeartbeatData heartbeatData = new HeartbeatData(); - - // clientID - heartbeatData.setClientID(this.clientId); + return true; + } - // Consumer - for (String group : this.consumerTable.keySet()) { - MQConsumerInner impl = this.consumerTable.get(group); - if (impl != null) { - ConsumerData consumerData = new ConsumerData(); - consumerData.setGroupName(impl.getGroupName()); - consumerData.setConsumeType(impl.getConsumeType()); - consumerData.setMessageModel(impl.getMessageModel()); - consumerData.getSubscriptionDataSet().addAll(impl.getMQSubscriptions()); - heartbeatData.getConsumerDataSet().add(consumerData); - } - } + public void unregisterConsumer(final String group) { + this.consumerTable.remove(group); + this.unregisterClientWithLock(null, group); + } - // Producer - for (String group : this.producerTable.keySet()) { - DefaultMQProducerImpl impl = this.producerTable.get(group); - if (impl != null) { - ProducerData producerData = new ProducerData(); - producerData.setGroupName(group); - heartbeatData.getProducerDataSet().add(producerData); + private void unregisterClientWithLock(final String producerGroup, final String consumerGroup) { + try { + if (this.lockHeartbeat.tryLock(LockTimeoutMillis, TimeUnit.MILLISECONDS)) { + try { + this.unregisterClient(producerGroup, consumerGroup); + } + catch (Exception e) { + log.error("unregisterClient exception", e); + } + finally { + this.lockHeartbeat.unlock(); + } + } + else { + log.warn("lock heartBeat, but failed."); } } - - return heartbeatData; + catch (InterruptedException e) { + log.warn("unregisterClientWithLock exception", e); + } } - private void sendHeartbeatToAllBroker() { - final HeartbeatData heartbeatData = this.prepareHeartbeatData(); - final boolean producerEmpty = heartbeatData.getProducerDataSet().isEmpty(); - final boolean consumerEmpty = heartbeatData.getConsumerDataSet().isEmpty(); - if (producerEmpty && consumerEmpty) { - log.warn("sending hearbeat, but no consumer and no producer"); - return; - } + private void unregisterClient(final String producerGroup, final String consumerGroup) { + Iterator>> it = this.brokerAddrTable.entrySet().iterator(); + while (it.hasNext()) { + Entry> entry = it.next(); + String brokerName = entry.getKey(); + HashMap oneTable = entry.getValue(); - for (String name : this.brokerAddrTable.keySet()) { - final HashMap oneTable = this.brokerAddrTable.get(name); if (oneTable != null) { for (Long id : oneTable.keySet()) { String addr = oneTable.get(id); if (addr != null) { - // ˵ֻProducerSlave - if (consumerEmpty) { - if (id != MixAll.MASTER_ID) - continue; - } - try { - this.mQClientAPIImpl.sendHearbeat(addr, heartbeatData, 3000); - log.debug("send heart beat to broker[{} {} {}] success", name, id, addr); - log.debug(heartbeatData.toString()); + this.mQClientAPIImpl.unregisterClient(addr, this.clientId, producerGroup, + consumerGroup, 3000); + log.info( + "unregister client[Producer: {} Consumer: {}] from broker[{} {} {}] success", + producerGroup, consumerGroup, brokerName, id, addr); } catch (RemotingException e) { - log.error("send heart beat to broker exception", e); + log.error("unregister client exception from broker: " + addr, e); } catch (MQBrokerException e) { - log.error("send heart beat to broker exception", e); + log.error("unregister client exception from broker: " + addr, e); } catch (InterruptedException e) { - log.error("send heart beat to broker exception", e); + log.error("unregister client exception from broker: " + addr, e); } } } @@ -343,7 +906,7 @@ public boolean registerProducer(final String group, final DefaultMQProducerImpl return false; } - DefaultMQProducerImpl prev = this.producerTable.putIfAbsent(group, producer); + MQProducerInner prev = this.producerTable.putIfAbsent(group, producer); if (prev != null) { log.warn("the producer group[{}] exist already.", group); return false; @@ -355,18 +918,18 @@ public boolean registerProducer(final String group, final DefaultMQProducerImpl public void unregisterProducer(final String group) { this.producerTable.remove(group); - this.unregisterClient(group, null); + this.unregisterClientWithLock(group, null); } - public boolean registerConsumer(final String group, final MQConsumerInner consumer) { - if (null == group || null == consumer) { + public boolean registerAdminExt(final String group, final MQAdminExtInner admin) { + if (null == group || null == admin) { return false; } - MQConsumerInner prev = this.consumerTable.putIfAbsent(group, consumer); + MQAdminExtInner prev = this.adminExtTable.putIfAbsent(group, admin); if (prev != null) { - log.warn("the consumer group[" + group + "] exist already."); + log.warn("the admin group[{}] exist already.", group); return false; } @@ -374,14 +937,43 @@ public boolean registerConsumer(final String group, final MQConsumerInner consum } - public void unregisterConsumer(final String group) { - this.consumerTable.remove(group); - this.unregisterClient(null, group); + public void unregisterAdminExt(final String group) { + this.adminExtTable.remove(group); + } + + + public void rebalanceImmediately() { + this.rebalanceService.wakeup(); + } + + + public void doRebalance() { + for (String group : this.consumerTable.keySet()) { + MQConsumerInner impl = this.consumerTable.get(group); + if (impl != null) { + try { + impl.doRebalance(); + } + catch (Exception e) { + log.error("doRebalance exception", e); + } + } + } + } + + + public MQProducerInner selectProducer(final String group) { + return this.producerTable.get(group); + } + + + public MQConsumerInner selectConsumer(final String group) { + return this.consumerTable.get(group); } /** - * ĽӿڲѯBrokerַMaster + * 管理类的接口查询Broker地址,Master优先 * * @param brokerName * @return @@ -393,7 +985,7 @@ public FindBrokerResult findBrokerAddressInAdmin(final String brokerName) { HashMap map = this.brokerAddrTable.get(brokerName); if (map != null && !map.isEmpty()) { - // TODO жSlaveܻÿζѡͬSlaveҪŻ + // TODO 如果有多个Slave,可能会每次都选中相同的Slave,这里需要优化 FOR_SEG: for (Map.Entry entry : map.entrySet()) { Long id = entry.getKey(); brokerAddr = entry.getValue(); @@ -421,7 +1013,7 @@ public FindBrokerResult findBrokerAddressInAdmin(final String brokerName) { /** - * ϢУѰBrokerַһMaster + * 发布消息过程中,寻找Broker地址,一定是找Master */ public String findBrokerAddressInPublish(final String brokerName) { HashMap map = this.brokerAddrTable.get(brokerName); @@ -434,11 +1026,12 @@ public String findBrokerAddressInPublish(final String brokerName) { /** - * ϢУѰBrokerַȡMasterSlaveɲ + * 订阅消息过程中,寻找Broker地址,取Master还是Slave由参数决定 */ public FindBrokerResult findBrokerAddressInSubscribe(// final String brokerName,// - final ConsumeFromWhichNode consumeFromWhichNode// + final long brokerId,// + final boolean onlyThisBroker// ) { String brokerAddr = null; boolean slave = false; @@ -446,51 +1039,17 @@ public FindBrokerResult findBrokerAddressInSubscribe(// HashMap map = this.brokerAddrTable.get(brokerName); if (map != null && !map.isEmpty()) { - // TODO жSlaveܻÿζѡͬSlaveҪŻ - FOR_SEG: for (Map.Entry entry : map.entrySet()) { - Long id = entry.getKey(); + brokerAddr = map.get(brokerId); + slave = (brokerId != MixAll.MASTER_ID); + found = (brokerAddr != null); + + // 尝试寻找其他Broker + if (!found && !onlyThisBroker) { + Entry entry = map.entrySet().iterator().next(); brokerAddr = entry.getValue(); - if (brokerAddr != null) { - switch (consumeFromWhichNode) { - case CONSUME_FROM_MASTER_FIRST: - found = true; - if (MixAll.MASTER_ID == id) { - slave = false; - break FOR_SEG; - } - else { - slave = true; - } - break; - case CONSUME_FROM_SLAVE_FIRST: - found = true; - if (MixAll.MASTER_ID != id) { - slave = true; - break FOR_SEG; - } - else { - slave = false; - } - break; - case CONSUME_FROM_MASTER_ONLY: - if (MixAll.MASTER_ID == id) { - found = true; - slave = false; - break FOR_SEG; - } - break; - case CONSUME_FROM_SLAVE_ONLY: - if (MixAll.MASTER_ID != id) { - found = true; - slave = true; - break FOR_SEG; - } - break; - default: - break; - } - } - } // end of for + slave = (entry.getKey() != MixAll.MASTER_ID); + found = true; + } } if (found) { @@ -501,85 +1060,122 @@ public FindBrokerResult findBrokerAddressInSubscribe(// } - public static TopicPublishInfo topicRouteData2TopicPublishInfo(final String topic, final TopicRouteData route) { - TopicPublishInfo info = new TopicPublishInfo(); - // ˳Ϣ - if (route.getOrderTopicConf() != null && route.getOrderTopicConf().length() > 0) { - String[] brokers = route.getOrderTopicConf().split(";"); - for (String broker : brokers) { - String[] item = broker.split(":"); - int nums = Integer.parseInt(item[1]); - for (int i = 0; i < nums; i++) { - MessageQueue mq = new MessageQueue(topic, item[0], i); - info.getMessageQueueList().add(mq); - } - } - - info.setOrderTopic(true); + public List findConsumerIdList(final String topic, final String group) { + String brokerAddr = this.findBrokerAddrByTopic(topic); + if (null == brokerAddr) { + this.updateTopicRouteInfoFromNameServer(topic); + brokerAddr = this.findBrokerAddrByTopic(topic); } - // ˳Ϣ - else { - List qds = route.getQueueDatas(); - // ԭ򣺼ʹû˳ϢģʽĬ϶е˳ͬõһ¡ - Collections.sort(qds); - for (QueueData qd : qds) { - if (MixAll.isWriteable(qd.getPerm())) { - for (int i = 0; i < qd.getWriteQueueNums(); i++) { - MessageQueue mq = new MessageQueue(topic, qd.getBrokerName(), i); - info.getMessageQueueList().add(mq); - } - } - } - info.setOrderTopic(false); + if (null != brokerAddr) { + try { + return this.mQClientAPIImpl.getConsumerIdListByGroup(brokerAddr, group, 3000); + } + catch (Exception e) { + log.warn("getConsumerIdListByGroup exception, " + brokerAddr + " " + group, e); + } } - return info; + return null; } - public static List topicRouteData2TopicSubscribeInfo(final String topic, - final TopicRouteData route) { - List mqList = new ArrayList(); - List qds = route.getQueueDatas(); - for (QueueData qd : qds) { - if (MixAll.isReadable(qd.getPerm())) { - for (int i = 0; i < qd.getWriteQueueNums(); i++) { - MessageQueue mq = new MessageQueue(topic, qd.getBrokerName(), i); - mqList.add(mq); - } + public String findBrokerAddrByTopic(final String topic) { + TopicRouteData topicRouteData = this.topicRouteTable.get(topic); + if (topicRouteData != null) { + List brokers = topicRouteData.getBrokerDatas(); + if (!brokers.isEmpty()) { + BrokerData bd = brokers.get(0); + return bd.selectBrokerAddr(); } } - return mqList; + return null; } - private void updateTopicRouteInfoFromNameServer() { - Set topicList = new HashSet(); + public void resetOffset(String topic, String group, Map offsetTable) { + DefaultMQPushConsumerImpl consumer = null; + try { + MQConsumerInner impl = this.consumerTable.get(group); + if (impl != null && impl instanceof DefaultMQPushConsumerImpl) { + consumer = (DefaultMQPushConsumerImpl) impl; + } + else { + log.info("[reset-offset] consumer dose not exist. group={}", group); + return; + } - // Consumer - for (String g : this.consumerTable.keySet()) { - MQConsumerInner impl = this.consumerTable.get(g); - if (impl != null) { - Set subList = impl.getMQSubscriptions(); - for (SubscriptionData subData : subList) { - topicList.add(subData.getTopic()); + // 设置当前的 processQueue 为 dropped,从而使得当前的 pullRequest 以及 + // consumerRequest 处理结束并销毁 + ConcurrentHashMap processQueueTable = + consumer.getRebalanceImpl().getProcessQueueTable(); + Iterator itr = processQueueTable.keySet().iterator(); + while (itr.hasNext()) { + MessageQueue mq = itr.next(); + if (topic.equals(mq.getTopic())) { + ProcessQueue pq = processQueueTable.get(mq); + pq.setDroped(true); + pq.clear(); } } - } - // Producer - for (String g : this.producerTable.keySet()) { - DefaultMQProducerImpl impl = this.producerTable.get(g); - if (impl != null) { - Set lst = impl.getPublishTopicList(); - topicList.addAll(lst); + // 更新消费队列的 offset 并提交到 broker + Iterator iterator = offsetTable.keySet().iterator(); + while (iterator.hasNext()) { + MessageQueue mq = iterator.next(); + consumer.updateConsumeOffset(mq, offsetTable.get(mq)); + log.info("[reset-offset] reset offsetTable. topic={}, group={}, mq={}, offset={}", + new Object[] { topic, group, mq, offsetTable.get(mq) }); + } + consumer.getOffsetStore().persistAll(offsetTable.keySet()); + + // 等待所有的 pullRequest 以及 consumerRequest 处理完成 + try { + TimeUnit.SECONDS.sleep(10); + } + catch (InterruptedException e) { + // + } + + // 更新消费队列的 offset 并提交到 broker + iterator = offsetTable.keySet().iterator(); + while (iterator.hasNext()) { + MessageQueue mq = iterator.next(); + consumer.updateConsumeOffset(mq, offsetTable.get(mq)); + log.info("[reset-offset] reset offsetTable. topic={}, group={}, mq={}, offset={}", + new Object[] { topic, group, mq, offsetTable.get(mq) }); + } + consumer.getOffsetStore().persistAll(offsetTable.keySet()); + + // 真正清除被 dropped 的 processQueue,从而使得新的 rebalance 生效,生成新的 pullRequest + // 以及 consumerRequest + iterator = offsetTable.keySet().iterator(); + processQueueTable = consumer.getRebalanceImpl().getProcessQueueTable(); + while (iterator.hasNext()) { + MessageQueue mq = iterator.next(); + processQueueTable.remove(mq); } } + finally { + // 放在 finally 主要是确保 rebalance 一定被执行 + consumer.getRebalanceImpl().doRebalance(); + } + } - for (String topic : topicList) { - this.updateTopicRouteInfoFromNameServer(topic); + + public Map getConsumerStatus(String topic, String group) { + MQConsumerInner impl = this.consumerTable.get(group); + if (impl != null && impl instanceof DefaultMQPushConsumerImpl) { + DefaultMQPushConsumerImpl consumer = (DefaultMQPushConsumerImpl) impl; + return consumer.getOffsetStore().cloneOffsetTable(topic); + } + else if (impl != null && impl instanceof DefaultMQPullConsumerImpl) { + DefaultMQPullConsumerImpl consumer = (DefaultMQPullConsumerImpl) impl; + return consumer.getOffsetStore().cloneOffsetTable(topic); + } + else { + return Collections.EMPTY_MAP; } } @@ -589,77 +1185,37 @@ public TopicRouteData getAnExistTopicRouteData(final String topic) { } - /** - * Name ServerӿڣTopicȡ·Ϣ - */ - public boolean updateTopicRouteInfoFromNameServer(final String topic) { - try { - if (this.lockNamesrv.tryLock(LockTimeoutMillis, TimeUnit.MILLISECONDS)) { - try { - TopicRouteData topicRouteData = - this.mQClientAPIImpl.getTopicRouteInfoFromNameServer(topic, 1000 * 3); - if (topicRouteData != null) { - TopicRouteData old = this.topicRouteTable.get(topic); - if (null == old || !old.equals(topicRouteData)) { - log.info("the topic[" + topic + "] route info changed, " + topicRouteData); - // BrokerַϢ - for (BrokerData bd : topicRouteData.getBrokerDatas()) { - this.brokerAddrTable.put(bd.getBrokerName(), bd.getBrokerAddrs()); - } + public MQClientAPIImpl getMQClientAPIImpl() { + return mQClientAPIImpl; + } - // ·Ϣ - TopicPublishInfo publishInfo = topicRouteData2TopicPublishInfo(topic, topicRouteData); - for (String g : this.producerTable.keySet()) { - DefaultMQProducerImpl impl = this.producerTable.get(g); - if (impl != null) { - impl.updateTopicPublishInfo(topic, publishInfo); - } - } - // ¶ĶϢ - // TODO + public MQAdminImpl getMQAdminImpl() { + return mQAdminImpl; + } - this.topicRouteTable.put(topic, topicRouteData); - return true; - } - } - } - catch (RemotingException e) { - log.warn("", e); - } - catch (MQClientException e) { - log.warn("", e); - } - catch (InterruptedException e) { - log.warn("", e); - } - catch (InvalidProtocolBufferException e) { - log.warn("", e); - } - finally { - this.lockNamesrv.unlock(); - } - } - } - catch (InterruptedException e) { - log.warn("", e); - } - return false; + public String getClientId() { + return clientId; } - public MQClientAPIImpl getMQClientAPIImpl() { - return mQClientAPIImpl; + public long getBootTimestamp() { + return bootTimestamp; } - public MQAdminImpl getMQAdminImpl() { - return mQAdminImpl; + public ScheduledExecutorService getScheduledExecutorService() { + return scheduledExecutorService; } - public String getClientId() { - return clientId; + public PullMessageService getPullMessageService() { + return pullMessageService; + } + + + public DefaultMQProducer getDefaultMQProducer() { + return defaultMQProducer; } } diff --git a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/impl/producer/DefaultMQProducerImpl.java b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/impl/producer/DefaultMQProducerImpl.java index dd691a47..94da4278 100644 --- a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/impl/producer/DefaultMQProducerImpl.java +++ b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/impl/producer/DefaultMQProducerImpl.java @@ -1,21 +1,45 @@ /** - * $Id: DefaultMQProducerImpl.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.client.impl.producer; import java.io.IOException; import java.net.UnknownHostException; +import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; +import java.util.concurrent.BlockingQueue; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; + +import org.slf4j.Logger; import com.alibaba.rocketmq.client.QueryResult; +import com.alibaba.rocketmq.client.Validators; import com.alibaba.rocketmq.client.exception.MQBrokerException; import com.alibaba.rocketmq.client.exception.MQClientException; +import com.alibaba.rocketmq.client.hook.SendMessageContext; +import com.alibaba.rocketmq.client.hook.SendMessageHook; import com.alibaba.rocketmq.client.impl.CommunicationMode; import com.alibaba.rocketmq.client.impl.MQClientManager; import com.alibaba.rocketmq.client.impl.factory.MQClientFactory; +import com.alibaba.rocketmq.client.log.ClientLogger; import com.alibaba.rocketmq.client.producer.DefaultMQProducer; import com.alibaba.rocketmq.client.producer.LocalTransactionExecuter; import com.alibaba.rocketmq.client.producer.LocalTransactionState; @@ -23,16 +47,21 @@ import com.alibaba.rocketmq.client.producer.SendCallback; import com.alibaba.rocketmq.client.producer.SendResult; import com.alibaba.rocketmq.client.producer.SendStatus; -import com.alibaba.rocketmq.common.Message; -import com.alibaba.rocketmq.common.MessageDecoder; -import com.alibaba.rocketmq.common.MessageExt; -import com.alibaba.rocketmq.common.MessageId; -import com.alibaba.rocketmq.common.MessageQueue; +import com.alibaba.rocketmq.client.producer.TransactionCheckListener; +import com.alibaba.rocketmq.client.producer.TransactionMQProducer; +import com.alibaba.rocketmq.client.producer.TransactionSendResult; import com.alibaba.rocketmq.common.MixAll; -import com.alibaba.rocketmq.common.UtilALl; import com.alibaba.rocketmq.common.ServiceState; -import com.alibaba.rocketmq.common.TopicFilterType; +import com.alibaba.rocketmq.common.UtilAll; +import com.alibaba.rocketmq.common.help.FAQUrl; +import com.alibaba.rocketmq.common.message.Message; +import com.alibaba.rocketmq.common.message.MessageConst; +import com.alibaba.rocketmq.common.message.MessageDecoder; +import com.alibaba.rocketmq.common.message.MessageExt; +import com.alibaba.rocketmq.common.message.MessageId; +import com.alibaba.rocketmq.common.message.MessageQueue; import com.alibaba.rocketmq.common.protocol.MQProtos.MQResponseCode; +import com.alibaba.rocketmq.common.protocol.header.CheckTransactionStateRequestHeader; import com.alibaba.rocketmq.common.protocol.header.EndTransactionRequestHeader; import com.alibaba.rocketmq.common.protocol.header.SendMessageRequestHeader; import com.alibaba.rocketmq.common.sysflag.MessageSysFlag; @@ -43,79 +72,171 @@ /** - * Ĭʵ + * 生产者默认实现 * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * @author shijia.wxr + * @since 2013-7-24 */ -public class DefaultMQProducerImpl { - private ServiceState serviceState = ServiceState.CREATE_JUST; - +public class DefaultMQProducerImpl implements MQProducerInner { + private final Logger log = ClientLogger.getLog(); private final DefaultMQProducer defaultMQProducer; - private final ConcurrentHashMap topicPublishInfoTable = new ConcurrentHashMap(); - + /** + * 事务相关 + */ + protected BlockingQueue checkRequestQueue; + protected ExecutorService checkExecutor; + private ServiceState serviceState = ServiceState.CREATE_JUST; private MQClientFactory mQClientFactory; + /** + * 发送每条消息会回调 + */ + private final ArrayList hookList = new ArrayList(); + public DefaultMQProducerImpl(final DefaultMQProducer defaultMQProducer) { this.defaultMQProducer = defaultMQProducer; } - private void checkConfig() throws MQClientException { - if (null == this.defaultMQProducer.getProducerGroup()) { - throw new MQClientException("producerGroup is null", null); + public void initTransactionEnv() { + TransactionMQProducer producer = (TransactionMQProducer) this.defaultMQProducer; + this.checkRequestQueue = new LinkedBlockingQueue(producer.getCheckRequestHoldMax()); + this.checkExecutor = new ThreadPoolExecutor(// + producer.getCheckThreadPoolMinSize(),// + producer.getCheckThreadPoolMaxSize(),// + 1000 * 60,// + TimeUnit.MILLISECONDS,// + this.checkRequestQueue); + } + + + public void destroyTransactionEnv() { + this.checkExecutor.shutdown(); + this.checkRequestQueue.clear(); + } + + + public boolean hasHook() { + return !this.hookList.isEmpty(); + } + + + public void registerHook(final SendMessageHook hook) { + this.hookList.add(hook); + log.info("register sendMessage Hook, {}", hook.hookName()); + } + + + public void executeHookBefore(final SendMessageContext context) { + if (!this.hookList.isEmpty()) { + for (SendMessageHook hook : this.hookList) { + try { + hook.sendMessageBefore(context); + } + catch (Throwable e) { + } + } } + } - if (this.defaultMQProducer.getProducerGroup().equals(MixAll.DEFAULT_PRODUCER_GROUP)) { - throw new MQClientException("producerGroup can not equal " + MixAll.DEFAULT_PRODUCER_GROUP - + ", please specify another one.", null); + + public void executeHookAfter(final SendMessageContext context) { + if (!this.hookList.isEmpty()) { + for (SendMessageHook hook : this.hookList) { + try { + hook.sendMessageAfter(context); + } + catch (Throwable e) { + } + } } } public void start() throws MQClientException { + this.start(true); + } + + + public void start(final boolean startFactory) throws MQClientException { switch (this.serviceState) { case CREATE_JUST: - this.checkConfig(); + this.serviceState = ServiceState.START_FAILED; - this.serviceState = ServiceState.RUNNING; + this.checkConfig(); this.mQClientFactory = - MQClientManager.getInstance().getAndCreateMQClientFactory( - this.defaultMQProducer.getMQClientConfig()); + MQClientManager.getInstance().getAndCreateMQClientFactory(this.defaultMQProducer); - boolean registerOK = mQClientFactory.registerProducer(this.defaultMQProducer.getProducerGroup(), this); + boolean registerOK = + mQClientFactory.registerProducer(this.defaultMQProducer.getProducerGroup(), this); if (!registerOK) { this.serviceState = ServiceState.CREATE_JUST; throw new MQClientException("The producer group[" + this.defaultMQProducer.getProducerGroup() - + "] has created already, specifed another name please.", null); + + "] has been created before, specify another name please." + + FAQUrl.suggestTodo(FAQUrl.GROUP_NAME_DUPLICATE_URL), null); } - // ĬTopicע - this.topicPublishInfoTable.put(this.defaultMQProducer.getCreateTopicKey(), new TopicPublishInfo()); + // 默认Topic注册 + this.topicPublishInfoTable + .put(this.defaultMQProducer.getCreateTopicKey(), new TopicPublishInfo()); - mQClientFactory.start(); + if (startFactory) { + mQClientFactory.start(); + } + + log.info("the producer [{}] start OK", this.defaultMQProducer.getProducerGroup()); + this.serviceState = ServiceState.RUNNING; break; case RUNNING: - break; + case START_FAILED: case SHUTDOWN_ALREADY: - break; + throw new MQClientException("The producer service state not OK, maybe started once, "// + + this.serviceState// + + FAQUrl.suggestTodo(FAQUrl.CLIENT_SERVICE_NOT_OK), null); default: break; } + + this.mQClientFactory.sendHeartbeatToAllBrokerWithLock(); + } + + + private void checkConfig() throws MQClientException { + // producerGroup 有效性检查 + Validators.checkGroup(this.defaultMQProducer.getProducerGroup()); + + if (null == this.defaultMQProducer.getProducerGroup()) { + throw new MQClientException("producerGroup is null", null); + } + + if (this.defaultMQProducer.getProducerGroup().equals(MixAll.DEFAULT_PRODUCER_GROUP)) { + throw new MQClientException("producerGroup can not equal " + MixAll.DEFAULT_PRODUCER_GROUP + + ", please specify another one.", null); + } } public void shutdown() { + this.shutdown(true); + } + + + public void shutdown(final boolean shutdownFactory) { switch (this.serviceState) { case CREATE_JUST: break; case RUNNING: - this.serviceState = ServiceState.SHUTDOWN_ALREADY; this.mQClientFactory.unregisterProducer(this.defaultMQProducer.getProducerGroup()); - this.mQClientFactory.shutdown(); + if (shutdownFactory) { + this.mQClientFactory.shutdown(); + } + + log.info("the producer [{}] shutdown OK", this.defaultMQProducer.getProducerGroup()); + this.serviceState = ServiceState.SHUTDOWN_ALREADY; break; case SHUTDOWN_ALREADY: break; @@ -125,37 +246,148 @@ public void shutdown() { } - private void makeSureStateOK() throws MQClientException { - if (this.serviceState != ServiceState.RUNNING) { - throw new MQClientException("The producer service state not OK", null); + @Override + public Set getPublishTopicList() { + Set topicList = new HashSet(); + for (String key : this.topicPublishInfoTable.keySet()) { + topicList.add(key); } + + return topicList; + } + + + @Override + public boolean isPublishTopicNeedUpdate(String topic) { + TopicPublishInfo prev = this.topicPublishInfoTable.get(topic); + + return null == prev || !prev.ok(); + } + + + @Override + public TransactionCheckListener checkListener() { + if (this.defaultMQProducer instanceof TransactionMQProducer) { + TransactionMQProducer producer = (TransactionMQProducer) defaultMQProducer; + return producer.getTransactionCheckListener(); + } + + return null; + } + + + @Override + public void checkTransactionState(final String addr, final MessageExt msg, + final CheckTransactionStateRequestHeader header) { + Runnable request = new Runnable() { + private final String brokerAddr = addr; + private final MessageExt message = msg; + private final CheckTransactionStateRequestHeader checkRequestHeader = header; + private final String group = DefaultMQProducerImpl.this.defaultMQProducer.getProducerGroup(); + + + @Override + public void run() { + TransactionCheckListener transactionCheckListener = + DefaultMQProducerImpl.this.checkListener(); + if (transactionCheckListener != null) { + LocalTransactionState localTransactionState = LocalTransactionState.UNKNOW; + Throwable exception = null; + try { + localTransactionState = transactionCheckListener.checkLocalTransactionState(message); + } + catch (Throwable e) { + log.error( + "Broker call checkTransactionState, but checkLocalTransactionState exception", e); + exception = e; + } + + this.processTransactionState(// + localTransactionState,// + group, // + exception); + } + else { + log.warn("checkTransactionState, pick transactionCheckListener by group[{}] failed", + group); + } + } + + + private void processTransactionState(// + final LocalTransactionState localTransactionState,// + final String producerGroup,// + final Throwable exception) { + final EndTransactionRequestHeader thisHeader = new EndTransactionRequestHeader(); + thisHeader.setCommitLogOffset(checkRequestHeader.getCommitLogOffset()); + thisHeader.setProducerGroup(producerGroup); + thisHeader.setTranStateTableOffset(checkRequestHeader.getTranStateTableOffset()); + thisHeader.setFromTransactionCheck(true); + thisHeader.setMsgId(message.getMsgId()); + switch (localTransactionState) { + case COMMIT_MESSAGE: + thisHeader.setCommitOrRollback(MessageSysFlag.TransactionCommitType); + break; + case ROLLBACK_MESSAGE: + thisHeader.setCommitOrRollback(MessageSysFlag.TransactionRollbackType); + log.warn("when broker check, client rollback this transaction, {}", thisHeader); + break; + case UNKNOW: + thisHeader.setCommitOrRollback(MessageSysFlag.TransactionNotType); + log.warn("when broker check, client donot know this transaction state, {}", thisHeader); + break; + default: + break; + } + + String remark = null; + if (exception != null) { + remark = + "checkLocalTransactionState Exception: " + + RemotingHelper.exceptionSimpleDesc(exception); + } + + try { + DefaultMQProducerImpl.this.mQClientFactory.getMQClientAPIImpl().endTransactionOneway( + brokerAddr, thisHeader, remark, 3000); + } + catch (Exception e) { + log.error("endTransactionOneway exception", e); + } + } + }; + + this.checkExecutor.submit(request); } + @Override public void updateTopicPublishInfo(final String topic, final TopicPublishInfo info) { if (info != null && topic != null) { TopicPublishInfo prev = this.topicPublishInfoTable.put(topic, info); if (prev != null) { - // TODO log + info.getSendWhichQueue().set(prev.getSendWhichQueue().get()); + log.info("updateTopicPublishInfo prev is not null, " + prev.toString()); } } } - public Set getPublishTopicList() { - Set topicList = new HashSet(); - for (String key : this.topicPublishInfoTable.keySet()) { - topicList.add(key); - } + public void createTopic(String key, String newTopic, int queueNum) throws MQClientException { + this.makeSureStateOK(); + // topic 有效性检查 + Validators.checkTopic(newTopic); - return topicList; + this.mQClientFactory.getMQAdminImpl().createTopic(key, newTopic, queueNum); } - public void createTopic(String key, String newTopic, int queueNum, TopicFilterType topicFilterType, - boolean order) throws MQClientException { - this.makeSureStateOK(); - this.mQClientFactory.getMQAdminImpl().createTopic(key, newTopic, queueNum, topicFilterType, order); + private void makeSureStateOK() throws MQClientException { + if (this.serviceState != ServiceState.RUNNING) { + throw new MQClientException("The producer service state not OK, "// + + this.serviceState// + + FAQUrl.suggestTodo(FAQUrl.CLIENT_SERVICE_NOT_OK), null); + } } @@ -171,26 +403,26 @@ public long searchOffset(MessageQueue mq, long timestamp) throws MQClientExcepti } - public long getMaxOffset(MessageQueue mq) throws MQClientException { + public long maxOffset(MessageQueue mq) throws MQClientException { this.makeSureStateOK(); - return this.mQClientFactory.getMQAdminImpl().getMaxOffset(mq); + return this.mQClientFactory.getMQAdminImpl().maxOffset(mq); } - public long getMinOffset(MessageQueue mq) throws MQClientException { + public long minOffset(MessageQueue mq) throws MQClientException { this.makeSureStateOK(); - return this.mQClientFactory.getMQAdminImpl().getMinOffset(mq); + return this.mQClientFactory.getMQAdminImpl().minOffset(mq); } - public long getEarliestMsgStoreTime(MessageQueue mq) throws MQClientException { + public long earliestMsgStoreTime(MessageQueue mq) throws MQClientException { this.makeSureStateOK(); - return this.mQClientFactory.getMQAdminImpl().getEarliestMsgStoreTime(mq); + return this.mQClientFactory.getMQAdminImpl().earliestMsgStoreTime(mq); } - public MessageExt viewMessage(String msgId) throws RemotingException, MQBrokerException, InterruptedException, - MQClientException { + public MessageExt viewMessage(String msgId) throws RemotingException, MQBrokerException, + InterruptedException, MQClientException { this.makeSureStateOK(); return this.mQClientFactory.getMQAdminImpl().viewMessage(msgId); @@ -204,40 +436,17 @@ public QueryResult queryMessage(String topic, String key, int maxNum, long begin } - private void checkMessage(Message msg) throws MQClientException { - // topic TODO - // tags TODO - // keys TODO - // body TODO - if (null == msg.getBody()) { - throw new MQClientException("the message body is null", null); - } - - if (msg.getBody().length > this.defaultMQProducer.getMaxMessageSize()) { - throw new MQClientException("the message body size over max value, MAX: " - + this.defaultMQProducer.getMaxMessageSize(), null); + /** + * DEFAULT ASYNC ------------------------------------------------------- + */ + public void send(Message msg, SendCallback sendCallback) throws MQClientException, RemotingException, + InterruptedException { + try { + this.sendDefaultImpl(msg, CommunicationMode.ASYNC, sendCallback); } - } - - - private boolean tryToCompressMessage(final Message msg) { - byte[] body = msg.getBody(); - if (body != null) { - if (body.length >= this.defaultMQProducer.getCompressMsgBodyOverHowmuch()) { - try { - byte[] data = UtilALl.compress(body, 9); - if (data != null) { - msg.setBody(data); - return true; - } - } - catch (IOException e) { - // TODO log - } - } + catch (MQBrokerException e) { + throw new MQClientException("unknow exception", e); } - - return false; } @@ -246,6 +455,10 @@ private SendResult sendDefaultImpl(// final CommunicationMode communicationMode,// final SendCallback sendCallback// ) throws MQClientException, RemotingException, MQBrokerException, InterruptedException { + // 有效性检查 + this.makeSureStateOK(); + Validators.checkMessage(msg, this.defaultMQProducer); + final long beginTimestamp = System.currentTimeMillis(); long endTimestamp = beginTimestamp; TopicPublishInfo topicPublishInfo = this.tryToFindTopicPublishInfo(msg.getTopic()); @@ -253,11 +466,13 @@ private SendResult sendDefaultImpl(// MessageQueue mq = null; Exception exception = null; SendResult sendResult = null; - for (int times = 0; times < 3 + int timesTotal = 1 + this.defaultMQProducer.getRetryTimesWhenSendFailed(); + for (int times = 0; times < timesTotal && (endTimestamp - beginTimestamp) < this.defaultMQProducer.getSendMsgTimeout(); times++) { String lastBrokerName = null == mq ? null : mq.getBrokerName(); - mq = topicPublishInfo.selectOneMessageQueue(lastBrokerName); - if (mq != null) { + MessageQueue tmpmq = topicPublishInfo.selectOneMessageQueue(lastBrokerName); + if (tmpmq != null) { + mq = tmpmq; try { sendResult = this.sendKernelImpl(msg, mq, communicationMode, sendCallback); endTimestamp = System.currentTimeMillis(); @@ -279,16 +494,22 @@ private SendResult sendDefaultImpl(// } } catch (RemotingException e) { + log.warn("sendKernelImpl exception", e); + log.warn(msg.toString()); exception = e; endTimestamp = System.currentTimeMillis(); continue; } catch (MQClientException e) { + log.warn("sendKernelImpl exception", e); + log.warn(msg.toString()); exception = e; endTimestamp = System.currentTimeMillis(); continue; } catch (MQBrokerException e) { + log.warn("sendKernelImpl exception", e); + log.warn(msg.toString()); exception = e; endTimestamp = System.currentTimeMillis(); switch (e.getResponseCode()) { @@ -306,6 +527,8 @@ private SendResult sendDefaultImpl(// } } catch (InterruptedException e) { + log.warn("sendKernelImpl exception", e); + log.warn(msg.toString()); throw e; } } @@ -321,7 +544,37 @@ private SendResult sendDefaultImpl(// throw new MQClientException("Retry many times, still failed", exception); } - throw new MQClientException("No route info of this topic, " + msg.getTopic(), null); + List nsList = this.getmQClientFactory().getMQClientAPIImpl().getNameServerAddressList(); + if (null == nsList || nsList.isEmpty()) { + // 说明没有设置Name Server地址 + throw new MQClientException("No name server address, please set it." + + FAQUrl.suggestTodo(FAQUrl.NAME_SERVER_ADDR_NOT_EXIST_URL), null); + } + + throw new MQClientException("No route info of this topic, " + msg.getTopic() + + FAQUrl.suggestTodo(FAQUrl.NO_TOPIC_ROUTE_INFO), null); + } + + + /** + * 尝试寻找Topic路由信息,如果没有则到Name Server上找,再没有,则取默认Topic + */ + private TopicPublishInfo tryToFindTopicPublishInfo(final String topic) { + TopicPublishInfo topicPublishInfo = this.topicPublishInfoTable.get(topic); + if (null == topicPublishInfo || !topicPublishInfo.ok()) { + this.topicPublishInfoTable.putIfAbsent(topic, new TopicPublishInfo()); + this.mQClientFactory.updateTopicRouteInfoFromNameServer(topic); + topicPublishInfo = this.topicPublishInfoTable.get(topic); + } + + if (topicPublishInfo != null && topicPublishInfo.ok()) { + return topicPublishInfo; + } + else { + this.mQClientFactory.updateTopicRouteInfoFromNameServer(topic, true, this.defaultMQProducer); + topicPublishInfo = this.topicPublishInfoTable.get(topic); + return topicPublishInfo; + } } @@ -332,12 +585,12 @@ private SendResult sendKernelImpl(final Message msg,// ) throws MQClientException, RemotingException, MQBrokerException, InterruptedException { String brokerAddr = this.mQClientFactory.findBrokerAddressInPublish(mq.getBrokerName()); if (null == brokerAddr) { - // TODO ˴ܶName ServerѹҪ - this.mQClientFactory.updateTopicRouteInfoFromNameServer(mq.getTopic()); - this.mQClientFactory.updateTopicRouteInfoFromNameServer(this.defaultMQProducer.getCreateTopicKey()); + // TODO 此处可能对Name Server压力过大,需要调优 + tryToFindTopicPublishInfo(mq.getTopic()); brokerAddr = this.mQClientFactory.findBrokerAddressInPublish(mq.getBrokerName()); } + SendMessageContext context = null; if (brokerAddr != null) { byte[] prevBody = msg.getBody(); try { @@ -346,11 +599,22 @@ private SendResult sendKernelImpl(final Message msg,// sysFlag |= MessageSysFlag.CompressedFlag; } - final String tranMsg = msg.getProperty(Message.PROPERTY_TRANSACTION_PREPARED); + final String tranMsg = msg.getProperty(MessageConst.PROPERTY_TRANSACTION_PREPARED); if (tranMsg != null && Boolean.parseBoolean(tranMsg)) { sysFlag |= MessageSysFlag.TransactionPreparedType; } + // 执行hook + if (this.hasHook()) { + context = new SendMessageContext(); + context.setProducerGroup(this.defaultMQProducer.getProducerGroup()); + context.setCommunicationMode(communicationMode); + context.setBrokerAddr(brokerAddr); + context.setMessage(msg); + context.setMq(mq); + this.executeHookBefore(context); + } + SendMessageRequestHeader requestHeader = new SendMessageRequestHeader(); requestHeader.setProducerGroup(this.defaultMQProducer.getProducerGroup()); requestHeader.setTopic(msg.getTopic()); @@ -372,94 +636,71 @@ private SendResult sendKernelImpl(final Message msg,// sendCallback// 7 ); + // 执行hook + if (this.hasHook()) { + context.setSendResult(sendResult); + this.executeHookAfter(context); + } + return sendResult; } - finally { - msg.setBody(prevBody); - } - } - - throw new MQClientException("The broker[" + mq.getBrokerName() + "] not exist", null); - } - - - private SendResult sendSelectImpl(// - Message msg,// - MessageQueueSelector selector,// - Object arg,// - final CommunicationMode communicationMode,// - final SendCallback sendCallback// - ) throws MQClientException, RemotingException, MQBrokerException, InterruptedException { - TopicPublishInfo topicPublishInfo = this.tryToFindTopicPublishInfo(msg.getTopic()); - if (topicPublishInfo != null && topicPublishInfo.ok()) { - MessageQueue mq = null; - try { - mq = selector.select(topicPublishInfo.getMessageQueueList(), msg, arg); + catch (RemotingException e) { + // 执行hook + if (this.hasHook()) { + context.setException(e); + this.executeHookAfter(context); + } + throw e; } - catch (Throwable e) { - throw new MQClientException("select message queue throwed exception.", e); + catch (MQBrokerException e) { + // 执行hook + if (this.hasHook()) { + context.setException(e); + this.executeHookAfter(context); + } + throw e; } - - if (mq != null) { - return this.sendKernelImpl(msg, mq, communicationMode, sendCallback); + catch (InterruptedException e) { + // 执行hook + if (this.hasHook()) { + context.setException(e); + this.executeHookAfter(context); + } + throw e; } - else { - throw new MQClientException("select message queue return null.", null); + finally { + msg.setBody(prevBody); } } - throw new MQClientException("No route info for this topic, " + msg.getTopic(), null); - } - - - /** - * ѰTopic·ϢûName ServerңûУȡĬTopic - */ - private TopicPublishInfo tryToFindTopicPublishInfo(final String topic) { - TopicPublishInfo topicPublishInfo = this.topicPublishInfoTable.get(topic); - if (null == topicPublishInfo) { - this.topicPublishInfoTable.putIfAbsent(topic, new TopicPublishInfo()); - this.mQClientFactory.updateTopicRouteInfoFromNameServer(topic); - this.mQClientFactory.updateTopicRouteInfoFromNameServer(this.defaultMQProducer.getCreateTopicKey()); - topicPublishInfo = this.topicPublishInfoTable.get(topic); - } - - if (topicPublishInfo != null && topicPublishInfo.ok()) { - return topicPublishInfo; - } - - return this.topicPublishInfoTable.get(this.defaultMQProducer.getCreateTopicKey()); - } - - - /** - * DEFAULT SYNC ------------------------------------------------------- - */ - public SendResult send(Message msg) throws MQClientException, RemotingException, MQBrokerException, - InterruptedException { - this.makeSureStateOK(); - - this.checkMessage(msg); - - return this.sendDefaultImpl(msg, CommunicationMode.SYNC, null); + throw new MQClientException("The broker[" + mq.getBrokerName() + "] not exist", null); } - /** - * DEFAULT ASYNC ------------------------------------------------------- + * 消息压缩level,默认5 */ - public void send(Message msg, SendCallback sendCallback) throws MQClientException, RemotingException, - InterruptedException { - this.makeSureStateOK(); + private int zipCompressLevel = Integer.parseInt(System.getProperty(MixAll.MESSAGE_COMPRESS_LEVEL, "5")); - this.checkMessage(msg); - try { - this.sendDefaultImpl(msg, CommunicationMode.ASYNC, sendCallback); - } - catch (MQBrokerException e) { - throw new MQClientException("unknow exception", e); + private boolean tryToCompressMessage(final Message msg) { + byte[] body = msg.getBody(); + if (body != null) { + if (body.length >= this.defaultMQProducer.getCompressMsgBodyOverHowmuch()) { + try { + byte[] data = UtilAll.compress(body, zipCompressLevel); + if (data != null) { + msg.setBody(data); + return true; + } + } + catch (IOException e) { + log.error("tryToCompressMessage exception", e); + log.warn(msg.toString()); + } + } } + + return false; } @@ -467,10 +708,6 @@ public void send(Message msg, SendCallback sendCallback) throws MQClientExceptio * DEFAULT ONEWAY ------------------------------------------------------- */ public void sendOneway(Message msg) throws MQClientException, RemotingException, InterruptedException { - this.makeSureStateOK(); - - this.checkMessage(msg); - try { this.sendDefaultImpl(msg, CommunicationMode.ONEWAY, null); } @@ -485,9 +722,13 @@ public void sendOneway(Message msg) throws MQClientException, RemotingException, */ public SendResult send(Message msg, MessageQueue mq) throws MQClientException, RemotingException, MQBrokerException, InterruptedException { + // 有效性检查 this.makeSureStateOK(); + Validators.checkMessage(msg, this.defaultMQProducer); - this.checkMessage(msg); + if (!msg.getTopic().equals(mq.getTopic())) { + throw new MQClientException("message's topic not equal mq's topic", null); + } return this.sendKernelImpl(msg, mq, CommunicationMode.SYNC, null); } @@ -498,9 +739,13 @@ public SendResult send(Message msg, MessageQueue mq) throws MQClientException, R */ public void send(Message msg, MessageQueue mq, SendCallback sendCallback) throws MQClientException, RemotingException, InterruptedException { + // 有效性检查 this.makeSureStateOK(); + Validators.checkMessage(msg, this.defaultMQProducer); - this.checkMessage(msg); + if (!msg.getTopic().equals(mq.getTopic())) { + throw new MQClientException("message's topic not equal mq's topic", null); + } try { this.sendKernelImpl(msg, mq, CommunicationMode.ASYNC, sendCallback); @@ -516,9 +761,9 @@ public void send(Message msg, MessageQueue mq, SendCallback sendCallback) throws */ public void sendOneway(Message msg, MessageQueue mq) throws MQClientException, RemotingException, InterruptedException { + // 有效性检查 this.makeSureStateOK(); - - this.checkMessage(msg); + Validators.checkMessage(msg, this.defaultMQProducer); try { this.sendKernelImpl(msg, mq, CommunicationMode.ONEWAY, null); @@ -538,6 +783,39 @@ public SendResult send(Message msg, MessageQueueSelector selector, Object arg) t } + private SendResult sendSelectImpl(// + Message msg,// + MessageQueueSelector selector,// + Object arg,// + final CommunicationMode communicationMode,// + final SendCallback sendCallback// + ) throws MQClientException, RemotingException, MQBrokerException, InterruptedException { + // 有效性检查 + this.makeSureStateOK(); + Validators.checkMessage(msg, this.defaultMQProducer); + + TopicPublishInfo topicPublishInfo = this.tryToFindTopicPublishInfo(msg.getTopic()); + if (topicPublishInfo != null && topicPublishInfo.ok()) { + MessageQueue mq = null; + try { + mq = selector.select(topicPublishInfo.getMessageQueueList(), msg, arg); + } + catch (Throwable e) { + throw new MQClientException("select message queue throwed exception.", e); + } + + if (mq != null) { + return this.sendKernelImpl(msg, mq, communicationMode, sendCallback); + } + else { + throw new MQClientException("select message queue return null.", null); + } + } + + throw new MQClientException("No route info for this topic, " + msg.getTopic(), null); + } + + /** * SELECT ASYNC ------------------------------------------------------- */ @@ -566,46 +844,16 @@ public void sendOneway(Message msg, MessageQueueSelector selector, Object arg) t } - private void endTransaction(final SendResult sendResult, final LocalTransactionState localTransactionState) - throws RemotingException, MQBrokerException, InterruptedException, UnknownHostException { - final MessageId id = MessageDecoder.decodeMessageId(sendResult.getMsgId()); - final String addr = RemotingUtil.socketAddress2String(id.getAddress()); - EndTransactionRequestHeader requestHeader = new EndTransactionRequestHeader(); - requestHeader.setCommitLogOffset(id.getOffset()); - switch (localTransactionState) { - case COMMIT_MESSAGE: - requestHeader.setCommitOrRollback(MessageSysFlag.TransactionCommitType); - break; - case ROLLBACK_MESSAGE: - requestHeader.setCommitOrRollback(MessageSysFlag.TransactionRollbackType); - break; - case UNKNOW: - break; - default: - break; - } - - requestHeader.setProducerGroup(this.defaultMQProducer.getProducerGroup()); - requestHeader.setTranStateTableOffset(sendResult.getQueueOffset()); - this.mQClientFactory.getMQClientAPIImpl().endTransaction(addr, requestHeader, - this.defaultMQProducer.getSendMsgTimeout()); - } - - - public SendResult sendMessageInTransaction(final Message msg, final LocalTransactionExecuter tranExecuter) - throws MQClientException { - if (null == msg) { - throw new MQClientException("msg is null", null); - } - + public TransactionSendResult sendMessageInTransaction(final Message msg, + final LocalTransactionExecuter tranExecuter, final Object arg) throws MQClientException { if (null == tranExecuter) { throw new MQClientException("tranExecuter is null", null); } - // һBrokerһPreparedϢ + // 第一步,向Broker发送一条Prepared消息 SendResult sendResult = null; - msg.putProperty(Message.PROPERTY_TRANSACTION_PREPARED, "true"); - msg.putProperty(Message.PROPERTY_PRODUCER_GROUP, this.defaultMQProducer.getProducerGroup()); + msg.putProperty(MessageConst.PROPERTY_TRANSACTION_PREPARED, "true"); + msg.putProperty(MessageConst.PROPERTY_PRODUCER_GROUP, this.defaultMQProducer.getProducerGroup()); try { sendResult = this.send(msg); } @@ -613,40 +861,104 @@ public SendResult sendMessageInTransaction(final Message msg, final LocalTransac throw new MQClientException("send message Exception", e); } - // ڶص + // 第二步,回调本地事务 LocalTransactionState localTransactionState = LocalTransactionState.UNKNOW; - MQClientException exception = null; + Throwable localException = null; try { - localTransactionState = tranExecuter.executeLocalTransactionBranch(msg); + localTransactionState = tranExecuter.executeLocalTransactionBranch(msg, arg); if (null == localTransactionState) { localTransactionState = LocalTransactionState.UNKNOW; } + + if (localTransactionState != LocalTransactionState.COMMIT_MESSAGE) { + log.info("executeLocalTransactionBranch return {}", localTransactionState); + log.info(msg.toString()); + } } catch (Throwable e) { - exception = - new MQClientException("send message OK, but execute local transaction branch Exception", e); + log.info("executeLocalTransactionBranch exception", e); + log.info(msg.toString()); + localException = e; + } + + // 第三步,提交或者回滚Broker端消息 + try { + this.endTransaction(sendResult, localTransactionState, localException); } + catch (Exception e) { + log.warn("local transaction execute " + localTransactionState + + ", but end broker transaction failed", e); + } + + TransactionSendResult transactionSendResult = new TransactionSendResult(); + transactionSendResult.setSendStatus(sendResult.getSendStatus()); + transactionSendResult.setMessageQueue(sendResult.getMessageQueue()); + transactionSendResult.setMsgId(sendResult.getMsgId()); + transactionSendResult.setQueueOffset(sendResult.getQueueOffset()); + transactionSendResult.setLocalTransactionState(localTransactionState); + return transactionSendResult; + } + - // ύ߻عBrokerϢ + private void endTransaction(// + final SendResult sendResult, // + final LocalTransactionState localTransactionState, // + final Throwable localException) throws RemotingException, MQBrokerException, + InterruptedException, UnknownHostException { + final MessageId id = MessageDecoder.decodeMessageId(sendResult.getMsgId()); + final String addr = RemotingUtil.socketAddress2String(id.getAddress()); + EndTransactionRequestHeader requestHeader = new EndTransactionRequestHeader(); + requestHeader.setCommitLogOffset(id.getOffset()); switch (localTransactionState) { case COMMIT_MESSAGE: + requestHeader.setCommitOrRollback(MessageSysFlag.TransactionCommitType); + break; case ROLLBACK_MESSAGE: - try { - this.endTransaction(sendResult, localTransactionState); - } - catch (Exception e) { - throw new MQClientException("local transaction execute " + localTransactionState - + ", but end broker transaction failed", e); - } + requestHeader.setCommitOrRollback(MessageSysFlag.TransactionRollbackType); break; - // ׳쳣߷δ֪״̬ʱύҲعȴcheck case UNKNOW: - // TODO log + requestHeader.setCommitOrRollback(MessageSysFlag.TransactionNotType); + break; default: break; - } - return sendResult; + requestHeader.setProducerGroup(this.defaultMQProducer.getProducerGroup()); + requestHeader.setTranStateTableOffset(sendResult.getQueueOffset()); + requestHeader.setMsgId(sendResult.getMsgId()); + String remark = + localException != null ? ("executeLocalTransactionBranch exception: " + localException + .toString()) : null; + this.mQClientFactory.getMQClientAPIImpl().endTransactionOneway(addr, requestHeader, remark, + this.defaultMQProducer.getSendMsgTimeout()); + } + + + /** + * DEFAULT SYNC ------------------------------------------------------- + */ + public SendResult send(Message msg) throws MQClientException, RemotingException, MQBrokerException, + InterruptedException { + return this.sendDefaultImpl(msg, CommunicationMode.SYNC, null); + } + + + public ConcurrentHashMap getTopicPublishInfoTable() { + return topicPublishInfoTable; + } + + + public MQClientFactory getmQClientFactory() { + return mQClientFactory; + } + + + public int getZipCompressLevel() { + return zipCompressLevel; + } + + + public void setZipCompressLevel(int zipCompressLevel) { + this.zipCompressLevel = zipCompressLevel; } } diff --git a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/impl/producer/MQProducerInner.java b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/impl/producer/MQProducerInner.java new file mode 100644 index 00000000..8a39c5e1 --- /dev/null +++ b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/impl/producer/MQProducerInner.java @@ -0,0 +1,48 @@ +/** + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.rocketmq.client.impl.producer; + +import java.util.Set; + +import com.alibaba.rocketmq.client.producer.TransactionCheckListener; +import com.alibaba.rocketmq.common.message.MessageExt; +import com.alibaba.rocketmq.common.protocol.header.CheckTransactionStateRequestHeader; + + +/** + * Producer内部接口 + * + * @author shijia.wxr + * @since 2013-7-24 + */ +public interface MQProducerInner { + public Set getPublishTopicList(); + + + public boolean isPublishTopicNeedUpdate(final String topic); + + + public TransactionCheckListener checkListener(); + + + public void checkTransactionState(// + final String addr, // + final MessageExt msg, // + final CheckTransactionStateRequestHeader checkRequestHeader); + + + public void updateTopicPublishInfo(final String topic, final TopicPublishInfo info); +} diff --git a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/impl/producer/SendResultExt.java b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/impl/producer/SendResultExt.java deleted file mode 100644 index f7e52aab..00000000 --- a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/impl/producer/SendResultExt.java +++ /dev/null @@ -1,22 +0,0 @@ -/** - * $Id: SendResultExt.java 1831 2013-05-16 01:39:51Z shijia.wxr $ - */ -package com.alibaba.rocketmq.client.impl.producer; - -import com.alibaba.rocketmq.client.producer.SendResult; -import com.alibaba.rocketmq.client.producer.SendStatus; -import com.alibaba.rocketmq.common.MessageQueue; - - -/** - * @author vintage.wang@gmail.com shijia.wxr@taobao.com - * - */ -public class SendResultExt extends SendResult { - private final long tranStateTableOffset = 0; - - - public SendResultExt(SendStatus sendStatus, String msgId, MessageQueue messageQueue, long queueOffset) { - super(sendStatus, msgId, messageQueue, queueOffset); - } -} diff --git a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/impl/producer/TopicPublishInfo.java b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/impl/producer/TopicPublishInfo.java index c332e04b..71e666c5 100644 --- a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/impl/producer/TopicPublishInfo.java +++ b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/impl/producer/TopicPublishInfo.java @@ -1,5 +1,17 @@ /** - * $Id: TopicPublishInfo.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.client.impl.producer; @@ -7,12 +19,14 @@ import java.util.List; import java.util.concurrent.atomic.AtomicInteger; -import com.alibaba.rocketmq.common.MessageQueue; +import com.alibaba.rocketmq.common.message.MessageQueue; /** - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * 发布Topic用到的路由信息 * + * @author shijia.wxr + * @since 2013-7-24 */ public class TopicPublishInfo { private boolean orderTopic = false; @@ -56,7 +70,7 @@ public void setSendWhichQueue(AtomicInteger sendWhichQueue) { /** - * lastBrokerNameΪnullѰ䲻ͬMessageQueue + * 如果lastBrokerName不为null,则寻找与其不同的MessageQueue */ public MessageQueue selectOneMessageQueue(final String lastBrokerName) { if (lastBrokerName != null) { @@ -77,4 +91,11 @@ public MessageQueue selectOneMessageQueue(final String lastBrokerName) { return this.messageQueueList.get(pos); } } + + + @Override + public String toString() { + return "TopicPublishInfo [orderTopic=" + orderTopic + ", messageQueueList=" + messageQueueList + + ", sendWhichQueue=" + sendWhichQueue + "]"; + } } diff --git a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/log/ClientLogger.java b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/log/ClientLogger.java new file mode 100644 index 00000000..e78bfae7 --- /dev/null +++ b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/log/ClientLogger.java @@ -0,0 +1,117 @@ +/** + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.rocketmq.client.log; + +import java.lang.reflect.Method; +import java.net.URL; + +import org.slf4j.ILoggerFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.alibaba.rocketmq.common.constant.LoggerName; + + +/** + * Client通过反射来初始化客户端日志 + * + * @author 菱叶 + * @since 2013-7-24 + */ +public class ClientLogger { + private static Logger log; + + static { + // 初始化Logger + log = createLogger(LoggerName.ClientLoggerName); + } + + + private static Logger createLogger(final String loggerName) { + String logConfigFilePath = + System.getProperty("rocketmq.client.log.configFile", + System.getenv("ROCKETMQ_CLIENT_LOG_CONFIGFILE")); + Boolean isloadconfig = + Boolean.parseBoolean(System.getProperty("rocketmq.client.log.loadconfig", "true")); + + final String log4j_resource_file = + System.getProperty("rocketmq.client.log4j.resource.fileName", "log4j_rocketmq_client.xml"); + + final String logback_resource_file = + System + .getProperty("rocketmq.client.logback.resource.fileName", "logback_rocketmq_client.xml"); + + if (isloadconfig) { + try { + ILoggerFactory iLoggerFactory = LoggerFactory.getILoggerFactory(); + Class classType = iLoggerFactory.getClass(); + if (classType.getName().equals("org.slf4j.impl.Log4jLoggerFactory")) { + Class DOMConfigurator = null; + Object DOMConfiguratorObj = null; + DOMConfigurator = Class.forName("org.apache.log4j.xml.DOMConfigurator"); + DOMConfiguratorObj = DOMConfigurator.newInstance(); + if (null == logConfigFilePath) { + // 如果应用没有配置,则使用jar包内置配置 + Method configure = DOMConfiguratorObj.getClass().getMethod("configure", URL.class); + URL url = ClientLogger.class.getClassLoader().getResource(log4j_resource_file); + configure.invoke(DOMConfiguratorObj, url); + } + else { + Method configure = DOMConfiguratorObj.getClass().getMethod("configure", String.class); + configure.invoke(DOMConfiguratorObj, logConfigFilePath); + } + + } + else if (classType.getName().equals("ch.qos.logback.classic.LoggerContext")) { + Class joranConfigurator = null; + Class context = Class.forName("ch.qos.logback.core.Context"); + Object joranConfiguratoroObj = null; + joranConfigurator = Class.forName("ch.qos.logback.classic.joran.JoranConfigurator"); + joranConfiguratoroObj = joranConfigurator.newInstance(); + Method setContext = joranConfiguratoroObj.getClass().getMethod("setContext", context); + setContext.invoke(joranConfiguratoroObj, iLoggerFactory); + if (null == logConfigFilePath) { + // 如果应用没有配置,则使用jar包内置配置 + URL url = ClientLogger.class.getClassLoader().getResource(logback_resource_file); + Method doConfigure = + joranConfiguratoroObj.getClass().getMethod("doConfigure", URL.class); + doConfigure.invoke(joranConfiguratoroObj, url); + } + else { + Method doConfigure = + joranConfiguratoroObj.getClass().getMethod("doConfigure", String.class); + doConfigure.invoke(joranConfiguratoroObj, logConfigFilePath); + } + + } + } + catch (Exception e) { + System.err.println(e); + } + } + return LoggerFactory.getLogger(LoggerName.ClientLoggerName); + } + + + public static Logger getLog() { + return log; + } + + + public static void setLog(Logger log) { + ClientLogger.log = log; + } +} diff --git a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/producer/DefaultMQProducer.java b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/producer/DefaultMQProducer.java index 244ead7a..29599a01 100644 --- a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/producer/DefaultMQProducer.java +++ b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/producer/DefaultMQProducer.java @@ -1,66 +1,75 @@ /** - * $Id: DefaultMQProducer.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.client.producer; import java.util.List; -import sun.reflect.generics.reflectiveObjects.NotImplementedException; - -import com.alibaba.rocketmq.client.MQClientConfig; +import com.alibaba.rocketmq.client.ClientConfig; import com.alibaba.rocketmq.client.QueryResult; import com.alibaba.rocketmq.client.exception.MQBrokerException; import com.alibaba.rocketmq.client.exception.MQClientException; import com.alibaba.rocketmq.client.impl.producer.DefaultMQProducerImpl; -import com.alibaba.rocketmq.common.Message; -import com.alibaba.rocketmq.common.MessageExt; import com.alibaba.rocketmq.common.MixAll; -import com.alibaba.rocketmq.common.MessageQueue; -import com.alibaba.rocketmq.common.TopicFilterType; +import com.alibaba.rocketmq.common.message.Message; +import com.alibaba.rocketmq.common.message.MessageExt; +import com.alibaba.rocketmq.common.message.MessageQueue; import com.alibaba.rocketmq.remoting.exception.RemotingException; /** - * Ϣߣʺʹspringʼ + * 消息生产者,适合使用spring初始化 * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * @author shijia.wxr + * @since 2013-7-25 */ -public class DefaultMQProducer implements MQProducer { - /** - * ͻ˹ã޸ - */ - private MQClientConfig mQClientConfig = new MQClientConfig(); +public class DefaultMQProducer extends ClientConfig implements MQProducer { + protected final transient DefaultMQProducerImpl defaultMQProducerImpl = new DefaultMQProducerImpl(this); /** - * һ㷢ͬϢProducerΪͬһGroupӦñã֤Ψһ + * 一般发送同样消息的Producer,归为同一个Group,应用必须设置,并保证命名唯一 */ private String producerGroup = MixAll.DEFAULT_PRODUCER_GROUP; /** - * ֧ڷϢʱTopicڣԶTopicҪָKey + * 支持在发送消息时,如果Topic不存在,自动创建Topic,但是要指定Key */ private String createTopicKey = MixAll.DEFAULT_TOPIC; /** - * ϢԶTopicʱĬ϶ + * 发送消息,自动创建Topic时,默认队列数 */ private volatile int defaultTopicQueueNums = 4; /** - * Ϣʱ޸ + * 发送消息超时,不建议修改 */ - private int sendMsgTimeout = 10000; + private int sendMsgTimeout = 3000; /** - * Message BodyСֵѹ + * Message Body大小超过阀值,则压缩 */ private int compressMsgBodyOverHowmuch = 1024 * 4; /** - * ϢѾɹдMasterˢ̳ʱͬSlaveʧܣһBroker޸Ĭֵ
- * ˳ϢЧ + * 发送失败后,重试几次 + */ + private int retryTimesWhenSendFailed = 2; + /** + * 消息已经成功写入Master,但是刷盘超时或者同步到Slave失败,则尝试重试另一个Broker,不建议修改默认值
+ * 顺序消息无效 */ private boolean retryAnotherBrokerWhenNotStoreOK = false; /** - * ϢСĬ512K + * 最大消息大小,默认512K */ - private int maxMessageSize = 1024 * 512; - - protected final DefaultMQProducerImpl defaultMQProducerImpl = new DefaultMQProducerImpl(this); + private int maxMessageSize = 1024 * 128; public DefaultMQProducer() { @@ -85,125 +94,122 @@ public void shutdown() { @Override - public SendResult send(Message msg) throws MQClientException, RemotingException, MQBrokerException, - InterruptedException { - return this.defaultMQProducerImpl.send(msg); + public List fetchPublishMessageQueues(String topic) throws MQClientException { + return this.defaultMQProducerImpl.fetchPublishMessageQueues(topic); } @Override - public SendResult send(Message msg, MessageQueueSelector selector, Object arg) throws MQClientException, - RemotingException, MQBrokerException, InterruptedException { - return this.defaultMQProducerImpl.send(msg, selector, arg); + public SendResult send(Message msg) throws MQClientException, RemotingException, MQBrokerException, + InterruptedException { + return this.defaultMQProducerImpl.send(msg); } @Override - public List fetchPublishMessageQueues(String topic) throws MQClientException { - return this.defaultMQProducerImpl.fetchPublishMessageQueues(topic); + public void send(Message msg, SendCallback sendCallback) throws MQClientException, RemotingException, + InterruptedException { + this.defaultMQProducerImpl.send(msg, sendCallback); } @Override - public long searchOffset(MessageQueue mq, long timestamp) throws MQClientException { - return this.defaultMQProducerImpl.searchOffset(mq, timestamp); + public void sendOneway(Message msg) throws MQClientException, RemotingException, InterruptedException { + this.defaultMQProducerImpl.sendOneway(msg); } @Override - public long getMaxOffset(MessageQueue mq) throws MQClientException { - return this.defaultMQProducerImpl.getMaxOffset(mq); + public SendResult send(Message msg, MessageQueue mq) throws MQClientException, RemotingException, + MQBrokerException, InterruptedException { + return this.defaultMQProducerImpl.send(msg, mq); } @Override - public long getMinOffset(MessageQueue mq) throws MQClientException { - return this.defaultMQProducerImpl.getMinOffset(mq); + public void send(Message msg, MessageQueue mq, SendCallback sendCallback) throws MQClientException, + RemotingException, InterruptedException { + this.defaultMQProducerImpl.send(msg, mq, sendCallback); } @Override - public long getEarliestMsgStoreTime(MessageQueue mq) throws MQClientException { - return this.defaultMQProducerImpl.getEarliestMsgStoreTime(mq); + public void sendOneway(Message msg, MessageQueue mq) throws MQClientException, RemotingException, + InterruptedException { + this.defaultMQProducerImpl.sendOneway(msg, mq); } @Override - public MessageExt viewMessage(String msgId) throws RemotingException, MQBrokerException, - InterruptedException, MQClientException { - return this.defaultMQProducerImpl.viewMessage(msgId); + public SendResult send(Message msg, MessageQueueSelector selector, Object arg) throws MQClientException, + RemotingException, MQBrokerException, InterruptedException { + return this.defaultMQProducerImpl.send(msg, selector, arg); } @Override - public SendResult send(Message msg, MessageQueue mq) throws MQClientException, RemotingException, - MQBrokerException, InterruptedException { - return this.defaultMQProducerImpl.send(msg, mq); + public void send(Message msg, MessageQueueSelector selector, Object arg, SendCallback sendCallback) + throws MQClientException, RemotingException, InterruptedException { + this.defaultMQProducerImpl.send(msg, selector, arg, sendCallback); } @Override - public void createTopic(String key, String newTopic, int queueNum, TopicFilterType topicFilterType, - boolean order) throws MQClientException { - this.defaultMQProducerImpl.createTopic(key, newTopic, queueNum, topicFilterType, order); + public void sendOneway(Message msg, MessageQueueSelector selector, Object arg) throws MQClientException, + RemotingException, InterruptedException { + this.defaultMQProducerImpl.sendOneway(msg, selector, arg); } @Override - public QueryResult queryMessage(String topic, String key, int maxNum, long begin, long end) - throws MQClientException, InterruptedException { - return this.defaultMQProducerImpl.queryMessage(topic, key, maxNum, begin, end); + public TransactionSendResult sendMessageInTransaction(Message msg, LocalTransactionExecuter tranExecuter, + final Object arg) throws MQClientException { + throw new RuntimeException( + "sendMessageInTransaction not implement, please use TransactionMQProducer class"); } @Override - public void send(Message msg, SendCallback sendCallback) throws MQClientException, RemotingException, - InterruptedException { - this.defaultMQProducerImpl.send(msg, sendCallback); + public void createTopic(String key, String newTopic, int queueNum) throws MQClientException { + this.defaultMQProducerImpl.createTopic(key, newTopic, queueNum); } @Override - public void sendOneway(Message msg) throws MQClientException, RemotingException, InterruptedException { - this.defaultMQProducerImpl.sendOneway(msg); + public long searchOffset(MessageQueue mq, long timestamp) throws MQClientException { + return this.defaultMQProducerImpl.searchOffset(mq, timestamp); } @Override - public void send(Message msg, MessageQueue mq, SendCallback sendCallback) throws MQClientException, - RemotingException, InterruptedException { - this.defaultMQProducerImpl.send(msg, mq, sendCallback); + public long maxOffset(MessageQueue mq) throws MQClientException { + return this.defaultMQProducerImpl.maxOffset(mq); } @Override - public void sendOneway(Message msg, MessageQueue mq) throws MQClientException, RemotingException, - InterruptedException { - this.defaultMQProducerImpl.sendOneway(msg, mq); + public long minOffset(MessageQueue mq) throws MQClientException { + return this.defaultMQProducerImpl.minOffset(mq); } @Override - public void send(Message msg, MessageQueueSelector selector, Object arg, SendCallback sendCallback) - throws MQClientException, RemotingException, InterruptedException { - this.defaultMQProducerImpl.send(msg, selector, arg, sendCallback); + public long earliestMsgStoreTime(MessageQueue mq) throws MQClientException { + return this.defaultMQProducerImpl.earliestMsgStoreTime(mq); } @Override - public void sendOneway(Message msg, MessageQueueSelector selector, Object arg) throws MQClientException, - RemotingException, InterruptedException { - this.defaultMQProducerImpl.sendOneway(msg, selector, arg); - } - - - public MQClientConfig getMQClientConfig() { - return mQClientConfig; + public MessageExt viewMessage(String msgId) throws RemotingException, MQBrokerException, + InterruptedException, MQClientException { + return this.defaultMQProducerImpl.viewMessage(msgId); } - public void setMQClientConfig(MQClientConfig mQClientConfig) { - this.mQClientConfig = mQClientConfig; + @Override + public QueryResult queryMessage(String topic, String key, int maxNum, long begin, long end) + throws MQClientException, InterruptedException { + return this.defaultMQProducerImpl.queryMessage(topic, key, maxNum, begin, end); } @@ -282,8 +288,12 @@ public void setDefaultTopicQueueNums(int defaultTopicQueueNums) { } - public SendResult sendMessageInTransaction(Message msg, LocalTransactionExecuter tranExecuter) - throws MQClientException { - throw new NotImplementedException(); + public int getRetryTimesWhenSendFailed() { + return retryTimesWhenSendFailed; + } + + + public void setRetryTimesWhenSendFailed(int retryTimesWhenSendFailed) { + this.retryTimesWhenSendFailed = retryTimesWhenSendFailed; } } diff --git a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/producer/LocalTransactionExecuter.java b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/producer/LocalTransactionExecuter.java index da7b711a..28017eee 100644 --- a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/producer/LocalTransactionExecuter.java +++ b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/producer/LocalTransactionExecuter.java @@ -1,17 +1,29 @@ /** - * $Id: LocalTransactionExecuter.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.client.producer; -import com.alibaba.rocketmq.common.Message; +import com.alibaba.rocketmq.common.message.Message; /** - * ִбɿͻ˻ص - * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * 执行本地事务,由客户端回调 * + * @author shijia.wxr + * @since 2013-7-25 */ public interface LocalTransactionExecuter { - public LocalTransactionState executeLocalTransactionBranch(final Message msg); + public LocalTransactionState executeLocalTransactionBranch(final Message msg, final Object arg); } diff --git a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/producer/LocalTransactionState.java b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/producer/LocalTransactionState.java index 5e966a22..5894bbeb 100644 --- a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/producer/LocalTransactionState.java +++ b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/producer/LocalTransactionState.java @@ -1,15 +1,30 @@ /** - * + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.client.producer; /** - * Producerִ״̬ + * Producer本地事务执行状态 * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * @author shijia.wxr + * @since 2013-7-25 */ public enum LocalTransactionState { + // 提交事务 COMMIT_MESSAGE, + // 回滚事务 ROLLBACK_MESSAGE, UNKNOW, } diff --git a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/producer/MQProducer.java b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/producer/MQProducer.java index c573e10e..b744c6e4 100644 --- a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/producer/MQProducer.java +++ b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/producer/MQProducer.java @@ -1,5 +1,17 @@ /** - * $Id: MQProducer.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.client.producer; @@ -8,19 +20,20 @@ import com.alibaba.rocketmq.client.MQAdmin; import com.alibaba.rocketmq.client.exception.MQBrokerException; import com.alibaba.rocketmq.client.exception.MQClientException; -import com.alibaba.rocketmq.common.Message; -import com.alibaba.rocketmq.common.MessageQueue; +import com.alibaba.rocketmq.common.message.Message; +import com.alibaba.rocketmq.common.message.MessageQueue; import com.alibaba.rocketmq.remoting.exception.RemotingException; /** - * Ϣ + * 消息生产者 * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * @author shijia.wxr + * @since 2013-7-25 */ public interface MQProducer extends MQAdmin { /** - * + * 启动服务 * * @throws MQClientException */ @@ -28,28 +41,28 @@ public interface MQProducer extends MQAdmin { /** - * رշ + * 关闭服务,一旦关闭,此对象将不可用 */ public void shutdown(); /** - * topicȡӦMessageQueue˳Ϣ˳Ϣ÷ + * 根据topic获取对应的MessageQueue,如果是顺序消息,则按照顺序消息配置返回 * * @param topic - * ϢTopic - * @return ضм + * 消息Topic + * @return 返回队列集合 * @throws MQClientException */ public List fetchPublishMessageQueues(final String topic) throws MQClientException; /** - * Ϣͬ + * 发送消息,同步调用 * * @param msg - * Ϣ - * @return ͽ + * 消息 + * @return 发送结果 * @throws InterruptedException * @throws MQBrokerException * @throws RemotingException @@ -60,12 +73,12 @@ public SendResult send(final Message msg) throws MQClientException, RemotingExce /** - * Ϣ첽 + * 发送消息,异步调用 * * @param msg - * Ϣ + * 消息 * @param sendCallback - * ͽͨ˽ӿڻص + * 发送结果通过此接口回调 * @throws MQClientException * @throws RemotingException * @throws InterruptedException @@ -75,43 +88,44 @@ public void send(final Message msg, final SendCallback sendCallback) throws MQCl /** - * ϢOnewayʽӦ޷֤ϢǷɹ + * 发送消息,Oneway形式,服务器不应答,无法保证消息是否成功到达服务器 * * @param msg - * Ϣ + * 消息 * @throws MQClientException * @throws RemotingException * @throws InterruptedException */ - public void sendOneway(final Message msg) throws MQClientException, RemotingException, InterruptedException; + public void sendOneway(final Message msg) throws MQClientException, RemotingException, + InterruptedException; /** - * ָзϢͬ + * 向指定队列发送消息,同步调用 * * @param msg - * Ϣ + * 消息 * @param mq - * - * @return ͽ + * 队列 + * @return 发送结果 * @throws InterruptedException * @throws MQBrokerException * @throws RemotingException * @throws MQClientException */ - public SendResult send(final Message msg, final MessageQueue mq) throws MQClientException, RemotingException, - MQBrokerException, InterruptedException; + public SendResult send(final Message msg, final MessageQueue mq) throws MQClientException, + RemotingException, MQBrokerException, InterruptedException; /** - * ָзϢ첽 + * 向指定队列发送消息,异步调用 * * @param msg - * Ϣ + * 消息 * @param mq - * + * 队列 * @param sendCallback - * ͽͨ˽ӿڻص + * 发送结果通过此接口回调 * @throws InterruptedException * @throws RemotingException * @throws MQClientException @@ -121,32 +135,32 @@ public void send(final Message msg, final MessageQueue mq, final SendCallback se /** - * ָзϢOnewayʽӦ޷֤ϢǷɹ + * 向指定队列发送消息,Oneway形式,服务器不应答,无法保证消息是否成功到达服务器 * * @param msg - * Ϣ + * 消息 * @param mq - * + * 队列 * @throws MQClientException * @throws RemotingException * @throws InterruptedException */ - public void sendOneway(final Message msg, final MessageQueue mq) throws MQClientException, RemotingException, - InterruptedException; + public void sendOneway(final Message msg, final MessageQueue mq) throws MQClientException, + RemotingException, InterruptedException; /** - * ϢԶѡУеܻBrokerͣ仯
- * Ҫ֤ϢϸάԱTopicʱҪر˵
- * ͬ + * 发送消息,可以自定义选择队列,队列的总数可能会由于Broker的启停变化
+ * 如果要保证消息严格有序,在向运维人员申请Topic时,需要特别说明
+ * 同步调用 * * @param msg - * Ϣ + * 消息 * @param selector - * ѡʱص + * 队列选择器,发送时会回调 * @param arg - * صѡʱ˲ᴫѡ񷽷 - * @return ͽ + * 回调队列选择器时,此参数会传入队列选择方法 + * @return 发送结果 * @throws InterruptedException * @throws MQBrokerException * @throws RemotingException @@ -157,37 +171,38 @@ public SendResult send(final Message msg, final MessageQueueSelector selector, f /** - * ϢԶѡУеܻBrokerͣ仯
- * Ҫ֤ϢϸάԱTopicʱҪر˵
- * 첽 + * 发送消息,可以自定义选择队列,队列的总数可能会由于Broker的启停变化
+ * 如果要保证消息严格有序,在向运维人员申请Topic时,需要特别说明
+ * 异步调用 * * @param msg - * Ϣ + * 消息 * @param selector - * ѡʱص + * 队列选择器,发送时会回调 * @param arg - * صѡʱ˲ᴫѡ񷽷 + * 回调队列选择器时,此参数会传入队列选择方法 * @param sendCallback - * ͽͨ˽ӿڻص + * 发送结果通过此接口回调 * @throws MQClientException * @throws RemotingException * @throws InterruptedException */ public void send(final Message msg, final MessageQueueSelector selector, final Object arg, - final SendCallback sendCallback) throws MQClientException, RemotingException, InterruptedException; + final SendCallback sendCallback) throws MQClientException, RemotingException, + InterruptedException; /** - * ϢԶѡУеܻBrokerͣ仯
- * Ҫ֤ϢϸάԱTopicʱҪر˵
- * OnewayʽӦ޷֤ϢǷɹ + * 发送消息,可以自定义选择队列,队列的总数可能会由于Broker的启停变化
+ * 如果要保证消息严格有序,在向运维人员申请Topic时,需要特别说明
+ * Oneway形式,服务器不应答,无法保证消息是否成功到达服务器 * * @param msg - * Ϣ + * 消息 * @param selector - * ѡʱص + * 队列选择器,发送时会回调 * @param arg - * صѡʱ˲ᴫѡ񷽷 + * 回调队列选择器时,此参数会传入队列选择方法 * @throws MQClientException * @throws RemotingException * @throws InterruptedException @@ -196,6 +211,6 @@ public void sendOneway(final Message msg, final MessageQueueSelector selector, f throws MQClientException, RemotingException, InterruptedException; - public SendResult sendMessageInTransaction(final Message msg, final LocalTransactionExecuter tranExecuter) - throws MQClientException; + public TransactionSendResult sendMessageInTransaction(final Message msg, + final LocalTransactionExecuter tranExecuter, final Object arg) throws MQClientException; } diff --git a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/producer/MessageQueueSelector.java b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/producer/MessageQueueSelector.java index f39b9386..71c67d3e 100644 --- a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/producer/MessageQueueSelector.java +++ b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/producer/MessageQueueSelector.java @@ -1,18 +1,31 @@ /** - * $Id: MessageQueueSelector.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.client.producer; import java.util.List; -import com.alibaba.rocketmq.common.Message; -import com.alibaba.rocketmq.common.MessageQueue; +import com.alibaba.rocketmq.common.message.Message; +import com.alibaba.rocketmq.common.message.MessageQueue; /** - * ѡ + * 队列选择器 * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * @author shijia.wxr + * @since 2013-7-25 */ public interface MessageQueueSelector { public MessageQueue select(final List mqs, final Message msg, final Object arg); diff --git a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/producer/SendCallback.java b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/producer/SendCallback.java index 2ba2944f..d2d94694 100644 --- a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/producer/SendCallback.java +++ b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/producer/SendCallback.java @@ -1,13 +1,25 @@ /** - * $Id: SendCallback.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.client.producer; /** - * 첽Ϣصӿ - * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * 异步发送消息回调接口 * + * @author shijia.wxr + * @since 2013-7-25 */ public interface SendCallback { public void onSuccess(final SendResult sendResult); diff --git a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/producer/SendResult.java b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/producer/SendResult.java index 6ae35c72..fe8ac0f9 100644 --- a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/producer/SendResult.java +++ b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/producer/SendResult.java @@ -1,28 +1,63 @@ /** - * $Id: SendResult.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.client.producer; -import com.alibaba.rocketmq.common.MessageQueue; +import com.alibaba.rocketmq.client.VirtualEnvUtil; +import com.alibaba.rocketmq.common.UtilAll; +import com.alibaba.rocketmq.common.message.MessageQueue; /** - * Ϣ + * 发送消息结果 * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * @author shijia.wxr + * @since 2013-7-25 */ public class SendResult { - private final SendStatus sendStatus; - private final String msgId; - private final MessageQueue messageQueue; - private final long queueOffset; + private SendStatus sendStatus; + private String msgId; + private MessageQueue messageQueue; + private long queueOffset; - public SendResult(SendStatus sendStatus, String msgId, MessageQueue messageQueue, long queueOffset) { + public SendResult() { + } + + + public SendResult(SendStatus sendStatus, String msgId, MessageQueue messageQueue, long queueOffset, + String projectGroupPrefix) { this.sendStatus = sendStatus; this.msgId = msgId; this.messageQueue = messageQueue; this.queueOffset = queueOffset; + // 清除虚拟运行环境相关的projectGroupPrefix + if (!UtilAll.isBlank(projectGroupPrefix)) { + this.messageQueue.setTopic(VirtualEnvUtil.clearProjectGroup(this.messageQueue.getTopic(), + projectGroupPrefix)); + } + } + + + public String getMsgId() { + return msgId; + } + + + public void setMsgId(String msgId) { + this.msgId = msgId; } @@ -31,8 +66,8 @@ public SendStatus getSendStatus() { } - public String getMsgId() { - return msgId; + public void setSendStatus(SendStatus sendStatus) { + this.sendStatus = sendStatus; } @@ -41,11 +76,21 @@ public MessageQueue getMessageQueue() { } + public void setMessageQueue(MessageQueue messageQueue) { + this.messageQueue = messageQueue; + } + + public long getQueueOffset() { return queueOffset; } + public void setQueueOffset(long queueOffset) { + this.queueOffset = queueOffset; + } + + @Override public String toString() { return "SendResult [sendStatus=" + sendStatus + ", msgId=" + msgId + ", messageQueue=" + messageQueue diff --git a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/producer/SendStatus.java b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/producer/SendStatus.java index 2a91482c..ad7dac02 100644 --- a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/producer/SendStatus.java +++ b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/producer/SendStatus.java @@ -1,17 +1,33 @@ /** - * $Id: SendStatus.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.client.producer; /** - * 4״̬ʾϢѾɹMaster - * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * 这4种状态都表示消息已经成功到达Master * + * @author shijia.wxr + * @since 2013-7-25 */ public enum SendStatus { + // 消息发送成功 SEND_OK, + // 消息发送成功,但是服务器刷盘超时,消息已经进入服务器队列,只有此时服务器宕机,消息才会丢失 FLUSH_DISK_TIMEOUT, + // 消息发送成功,但是服务器同步到Slave时超时,消息已经进入服务器队列,只有此时服务器宕机,消息才会丢失 FLUSH_SLAVE_TIMEOUT, + // 消息发送成功,但是此时slave不可用,消息已经进入服务器队列,只有此时服务器宕机,消息才会丢失 SLAVE_NOT_AVAILABLE } diff --git a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/producer/TransactionCheckListener.java b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/producer/TransactionCheckListener.java index 17136170..7a79f3f5 100644 --- a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/producer/TransactionCheckListener.java +++ b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/producer/TransactionCheckListener.java @@ -1,16 +1,28 @@ /** - * $Id: TransactionCheckListener.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.client.producer; -import com.alibaba.rocketmq.common.MessageExt; +import com.alibaba.rocketmq.common.message.MessageExt; /** - * صProducer鱾֧ɹʧ - * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * 服务器回调Producer,检查本地事务分支成功还是失败 * + * @author shijia.wxr + * @since 2013-7-25 */ public interface TransactionCheckListener { public LocalTransactionState checkLocalTransactionState(final MessageExt msg); diff --git a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/producer/TransactionMQProducer.java b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/producer/TransactionMQProducer.java index a5f2ae30..798b7f0d 100644 --- a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/producer/TransactionMQProducer.java +++ b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/producer/TransactionMQProducer.java @@ -1,20 +1,44 @@ /** - * $Id: TransactionMQProducer.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.client.producer; import com.alibaba.rocketmq.client.exception.MQClientException; -import com.alibaba.rocketmq.common.Message; +import com.alibaba.rocketmq.common.message.Message; /** - * ֲַ֧ʽProducer - * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * 支持分布式事务Producer * + * @author shijia.wxr + * @since 2013-7-25 */ public class TransactionMQProducer extends DefaultMQProducer { private TransactionCheckListener transactionCheckListener; + /** + * 事务回查最小并发数 + */ + private int checkThreadPoolMinSize = 1; + /** + * 事务回查最大并发数 + */ + private int checkThreadPoolMaxSize = 1; + /** + * 事务回查队列数 + */ + private int checkRequestHoldMax = 2000; public TransactionMQProducer() { @@ -26,13 +50,28 @@ public TransactionMQProducer(final String producerGroup) { } - public SendResult sendMessageInTransaction(final Message msg, final LocalTransactionExecuter tranExecuter) - throws MQClientException { + @Override + public void start() throws MQClientException { + this.defaultMQProducerImpl.initTransactionEnv(); + super.start(); + } + + + @Override + public void shutdown() { + super.shutdown(); + this.defaultMQProducerImpl.destroyTransactionEnv(); + } + + + @Override + public TransactionSendResult sendMessageInTransaction(final Message msg, + final LocalTransactionExecuter tranExecuter, final Object arg) throws MQClientException { if (null == this.transactionCheckListener) { throw new MQClientException("localTransactionBranchCheckListener is null", null); } - return this.defaultMQProducerImpl.sendMessageInTransaction(msg, tranExecuter); + return this.defaultMQProducerImpl.sendMessageInTransaction(msg, tranExecuter, arg); } @@ -44,4 +83,34 @@ public TransactionCheckListener getTransactionCheckListener() { public void setTransactionCheckListener(TransactionCheckListener transactionCheckListener) { this.transactionCheckListener = transactionCheckListener; } + + + public int getCheckThreadPoolMinSize() { + return checkThreadPoolMinSize; + } + + + public void setCheckThreadPoolMinSize(int checkThreadPoolMinSize) { + this.checkThreadPoolMinSize = checkThreadPoolMinSize; + } + + + public int getCheckThreadPoolMaxSize() { + return checkThreadPoolMaxSize; + } + + + public void setCheckThreadPoolMaxSize(int checkThreadPoolMaxSize) { + this.checkThreadPoolMaxSize = checkThreadPoolMaxSize; + } + + + public int getCheckRequestHoldMax() { + return checkRequestHoldMax; + } + + + public void setCheckRequestHoldMax(int checkRequestHoldMax) { + this.checkRequestHoldMax = checkRequestHoldMax; + } } diff --git a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/producer/TransactionSendResult.java b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/producer/TransactionSendResult.java new file mode 100644 index 00000000..c2e10189 --- /dev/null +++ b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/producer/TransactionSendResult.java @@ -0,0 +1,40 @@ +/** + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.rocketmq.client.producer; + +/** + * 发送事务消息返回结果 + * + * @author shijia.wxr + * @since 2013-7-31 + */ +public class TransactionSendResult extends SendResult { + private LocalTransactionState localTransactionState; + + + public TransactionSendResult() { + } + + + public LocalTransactionState getLocalTransactionState() { + return localTransactionState; + } + + + public void setLocalTransactionState(LocalTransactionState localTransactionState) { + this.localTransactionState = localTransactionState; + } +} diff --git a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/producer/selector/SelectMessageQueueByHash.java b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/producer/selector/SelectMessageQueueByHash.java new file mode 100644 index 00000000..9d8ef368 --- /dev/null +++ b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/producer/selector/SelectMessageQueueByHash.java @@ -0,0 +1,43 @@ +/** + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.rocketmq.client.producer.selector; + +import java.util.List; + +import com.alibaba.rocketmq.client.producer.MessageQueueSelector; +import com.alibaba.rocketmq.common.message.Message; +import com.alibaba.rocketmq.common.message.MessageQueue; + + +/** + * 使用哈希算法来选择队列,顺序消息通常都这样做
+ * + * @author shijia.wxr + * @since 2013-6-27 + */ +public class SelectMessageQueueByHash implements MessageQueueSelector { + + @Override + public MessageQueue select(List mqs, Message msg, Object arg) { + int value = arg.hashCode(); + if (value < 0) { + value = Math.abs(value); + } + + value = value % mqs.size(); + return mqs.get(value); + } +} diff --git a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/producer/selector/SelectMessageQueueByMachineRoom.java b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/producer/selector/SelectMessageQueueByMachineRoom.java index c9baceee..903cafb5 100644 --- a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/producer/selector/SelectMessageQueueByMachineRoom.java +++ b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/producer/selector/SelectMessageQueueByMachineRoom.java @@ -1,26 +1,51 @@ /** - * $Id: SelectMessageQueueByMachineRoom.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.client.producer.selector; import java.util.List; +import java.util.Set; import com.alibaba.rocketmq.client.producer.MessageQueueSelector; -import com.alibaba.rocketmq.common.Message; -import com.alibaba.rocketmq.common.MessageQueue; +import com.alibaba.rocketmq.common.message.Message; +import com.alibaba.rocketmq.common.message.MessageQueue; /** - * ݻѡĸУ֧߼ʹ - * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * 根据机房来选择发往哪个队列,支付宝逻辑机房使用 * + * @author shijia.wxr + * @since 2013-7-25 */ public class SelectMessageQueueByMachineRoom implements MessageQueueSelector { + private Set consumeridcs; + @Override public MessageQueue select(List mqs, Message msg, Object arg) { // TODO Auto-generated method stub return null; } + + + public Set getConsumeridcs() { + return consumeridcs; + } + + + public void setConsumeridcs(Set consumeridcs) { + this.consumeridcs = consumeridcs; + } } diff --git a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/producer/selector/SelectMessageQueueByRandoom.java b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/producer/selector/SelectMessageQueueByRandoom.java new file mode 100644 index 00000000..e5d745aa --- /dev/null +++ b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/producer/selector/SelectMessageQueueByRandoom.java @@ -0,0 +1,46 @@ +/** + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.rocketmq.client.producer.selector; + +import java.util.List; +import java.util.Random; + +import com.alibaba.rocketmq.client.producer.MessageQueueSelector; +import com.alibaba.rocketmq.common.message.Message; +import com.alibaba.rocketmq.common.message.MessageQueue; + + +/** + * 发送消息,随机选择队列 + * + * @author shijia.wxr + * @since 2013-7-25 + */ +public class SelectMessageQueueByRandoom implements MessageQueueSelector { + private Random random = new Random(System.currentTimeMillis()); + + + @Override + public MessageQueue select(List mqs, Message msg, Object arg) { + int value = random.nextInt(); + if (value < 0) { + value = Math.abs(value); + } + + value = value % mqs.size(); + return mqs.get(value); + } +} diff --git a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/stat/ConsumerStat.java b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/stat/ConsumerStat.java new file mode 100644 index 00000000..bf84f562 --- /dev/null +++ b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/stat/ConsumerStat.java @@ -0,0 +1,97 @@ +/** + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.rocketmq.client.stat; + +import java.util.concurrent.atomic.AtomicLong; + + +/** + * Consumer内部运行时统计信息 + * + * @author shijia.wxr + * @since 2013-7-7 + */ +public class ConsumerStat { + // 打点时间戳 + private long createTimestamp = System.currentTimeMillis(); + + // 一次消费消息的最大RT + private final AtomicLong consumeMsgRTMax = new AtomicLong(0); + // 每次消费消息RT叠加总和 + private final AtomicLong consumeMsgRTTotal = new AtomicLong(0); + // 消费消息成功次数总和 + private final AtomicLong consumeMsgOKTotal = new AtomicLong(0); + // 消费消息失败次数总和 + private final AtomicLong consumeMsgFailedTotal = new AtomicLong(0); + + // 拉消息RT叠加总和(只包含成功拉到的) + private final AtomicLong pullRTTotal = new AtomicLong(0); + // 拉消息次数(只包含成功拉到的) + private final AtomicLong pullTimesTotal = new AtomicLong(0); + + + public ConsumerStat createSnapshot() { + ConsumerStat consumerStat = new ConsumerStat(); + consumerStat.getConsumeMsgRTMax().set(this.consumeMsgRTMax.get()); + consumerStat.getConsumeMsgRTTotal().set(this.consumeMsgRTTotal.get()); + consumerStat.getConsumeMsgOKTotal().set(this.consumeMsgOKTotal.get()); + consumerStat.getConsumeMsgFailedTotal().set(this.consumeMsgFailedTotal.get()); + consumerStat.getPullRTTotal().set(this.pullRTTotal.get()); + consumerStat.getPullTimesTotal().set(this.pullTimesTotal.get()); + + return consumerStat; + } + + + public AtomicLong getConsumeMsgRTMax() { + return consumeMsgRTMax; + } + + + public AtomicLong getConsumeMsgRTTotal() { + return consumeMsgRTTotal; + } + + + public AtomicLong getConsumeMsgOKTotal() { + return consumeMsgOKTotal; + } + + + public AtomicLong getConsumeMsgFailedTotal() { + return consumeMsgFailedTotal; + } + + + public long getCreateTimestamp() { + return createTimestamp; + } + + + public void setCreateTimestamp(long createTimestamp) { + this.createTimestamp = createTimestamp; + } + + + public AtomicLong getPullTimesTotal() { + return pullTimesTotal; + } + + + public AtomicLong getPullRTTotal() { + return pullRTTotal; + } +} diff --git a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/stat/ConsumerStatManager.java b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/stat/ConsumerStatManager.java new file mode 100644 index 00000000..4cdd9fff --- /dev/null +++ b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/stat/ConsumerStatManager.java @@ -0,0 +1,109 @@ +/** + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.rocketmq.client.stat; + +import java.util.LinkedList; + +import org.slf4j.Logger; + +import com.alibaba.rocketmq.client.log.ClientLogger; + + +/** + * 用来统计Consumer运行状态 + * + * @author shijia.wxr + * @since 2013-7-7 + */ +public class ConsumerStatManager { + private final Logger log = ClientLogger.getLog(); + private final ConsumerStat consumertat = new ConsumerStat(); + private final LinkedList snapshotList = new LinkedList(); + + + public ConsumerStat getConsumertat() { + return consumertat; + } + + + public LinkedList getSnapshotList() { + return snapshotList; + } + + + /** + * 每隔1秒记录一次 + */ + public void recordSnapshotPeriodically() { + snapshotList.addLast(consumertat.createSnapshot()); + if (snapshotList.size() > 60) { + snapshotList.removeFirst(); + } + } + + + /** + * 每隔1分钟记录一次 + */ + public void logStatsPeriodically(final String group, final String clientId) { + if (this.snapshotList.size() >= 60) { + ConsumerStat first = this.snapshotList.getFirst(); + ConsumerStat last = this.snapshotList.getLast(); + + // 消费情况 + { + double avgRT = (last.getConsumeMsgRTTotal().get() - first.getConsumeMsgRTTotal().get()) // + / // + (double) ((last.getConsumeMsgOKTotal().get() + last.getConsumeMsgFailedTotal().get()) // + - // + (first.getConsumeMsgOKTotal().get() + first.getConsumeMsgFailedTotal().get())); + + double tps = ((last.getConsumeMsgOKTotal().get() + last.getConsumeMsgFailedTotal().get()) // + - // + (first.getConsumeMsgOKTotal().get() + first.getConsumeMsgFailedTotal().get()))// + / // + (double) (last.getCreateTimestamp() - first.getCreateTimestamp()); + + tps *= 1000; + + log.info( + "Consumer, {} {}, ConsumeAvgRT(ms): {} ConsumeMaxRT(ms): {} TotalOKMsg: {} TotalFailedMsg: {} consumeTPS: {}",// + group, // + clientId, // + avgRT, // + last.getConsumeMsgRTMax(), // + last.getConsumeMsgOKTotal(), // + last.getConsumeMsgFailedTotal(), // + tps// + ); + } + + // 拉消息情况 + { + double avgRT = (last.getPullRTTotal().get() - first.getPullRTTotal().get()) // + / // + (double) (last.getPullTimesTotal().get() - first.getPullTimesTotal().get()); + + log.info("Consumer, {} {}, PullAvgRT(ms): {} PullTimesTotal: {}",// + group, // + clientId, // + avgRT, // + last.getPullTimesTotal() // + ); + } + } + } +} diff --git a/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/stat/ProducerStat.java b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/stat/ProducerStat.java new file mode 100644 index 00000000..d60c0b83 --- /dev/null +++ b/rocketmq-client/src/main/java/com/alibaba/rocketmq/client/stat/ProducerStat.java @@ -0,0 +1,24 @@ +/** + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.rocketmq.client.stat; + +/** + * @author shijia.wxr + * @since 2013-7-7 + */ +public class ProducerStat { + +} diff --git a/rocketmq-client/src/main/resources/log4j_rocketmq_client.xml b/rocketmq-client/src/main/resources/log4j_rocketmq_client.xml new file mode 100644 index 00000000..4ed63c0a --- /dev/null +++ b/rocketmq-client/src/main/resources/log4j_rocketmq_client.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/rocketmq-client/src/main/resources/logback_rocketmq_client.xml b/rocketmq-client/src/main/resources/logback_rocketmq_client.xml new file mode 100644 index 00000000..66dd6c0e --- /dev/null +++ b/rocketmq-client/src/main/resources/logback_rocketmq_client.xml @@ -0,0 +1,41 @@ + + + + + ${user.home}/logs/rocketmqlogs/rocketmq_client.log + true + + ${user.home}/logs/rocketmqlogs/otherdays/rocketmq_client-%d{yyyy-MM-dd}.%i.log + + + 104857600 + + 10 + + + %d{yyy-MM-dd HH:mm:ss,GMT+8} %p %t - %m%n + UTF-8 + + + + + + + + + + + + + + + + + + + + + + diff --git a/rocketmq-client/src/test/java/com/alibaba/rocketmq/client/TestMultiConsumerProducer.java b/rocketmq-client/src/test/java/com/alibaba/rocketmq/client/TestMultiConsumerProducer.java new file mode 100644 index 00000000..4bb2cd9c --- /dev/null +++ b/rocketmq-client/src/test/java/com/alibaba/rocketmq/client/TestMultiConsumerProducer.java @@ -0,0 +1,72 @@ +package com.alibaba.rocketmq.client; + +import java.util.List; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicLong; + +import org.junit.Test; + +import com.alibaba.rocketmq.client.consumer.DefaultMQPushConsumer; +import com.alibaba.rocketmq.client.consumer.listener.ConsumeConcurrentlyContext; +import com.alibaba.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus; +import com.alibaba.rocketmq.client.consumer.listener.MessageListenerConcurrently; +import com.alibaba.rocketmq.client.exception.MQClientException; +import com.alibaba.rocketmq.client.producer.DefaultMQProducer; +import com.alibaba.rocketmq.client.producer.SendResult; +import com.alibaba.rocketmq.common.consumer.ConsumeFromWhere; +import com.alibaba.rocketmq.common.message.Message; +import com.alibaba.rocketmq.common.message.MessageExt; + + +public class TestMultiConsumerProducer { + private static final String TOPIC_TEST = "TopicTest-fundmng"; + + + @Test + public void testProducerConsumer() throws MQClientException, InterruptedException { + System.setProperty("rocketmq.namesrv.domain", "jmenv.tbsite.alipay.net"); + + DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("S_fundmng_demo_producer"); + DefaultMQProducer producer = new DefaultMQProducer("P_fundmng_demo_producer"); + + consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_LAST_OFFSET); + consumer.subscribe(TOPIC_TEST, null); + + final AtomicLong lastReceivedMills = new AtomicLong(System.currentTimeMillis()); + + final AtomicLong consumeTimes = new AtomicLong(0); + + consumer.registerMessageListener(new MessageListenerConcurrently() { + public ConsumeConcurrentlyStatus consumeMessage(final List msgs, + final ConsumeConcurrentlyContext context) { + System.out.println("接收了" + consumeTimes.incrementAndGet() + "条消息!"); + + lastReceivedMills.set(System.currentTimeMillis()); + + return ConsumeConcurrentlyStatus.CONSUME_SUCCESS; + } + }); + + consumer.start(); + producer.start(); + + for (int i = 0; i < 100; i++) { + try { + Message msg = new Message(TOPIC_TEST, ("Hello RocketMQ " + i).getBytes()); + SendResult sendResult = producer.send(msg); + System.out.println(sendResult); + } + catch (Exception e) { + TimeUnit.SECONDS.sleep(1); + } + } + + // wait no messages + while ((System.currentTimeMillis() - lastReceivedMills.get()) < 5000) { + TimeUnit.MILLISECONDS.sleep(200); + } + + consumer.shutdown(); + producer.shutdown(); + } +} diff --git a/rocketmq-client/src/test/java/com/alibaba/rocketmq/client/consumer/loadbalance/AllocateMessageQueueAveragelyTeset.java b/rocketmq-client/src/test/java/com/alibaba/rocketmq/client/consumer/loadbalance/AllocateMessageQueueAveragelyTeset.java deleted file mode 100644 index 744f12e8..00000000 --- a/rocketmq-client/src/test/java/com/alibaba/rocketmq/client/consumer/loadbalance/AllocateMessageQueueAveragelyTeset.java +++ /dev/null @@ -1,40 +0,0 @@ -/** - * $Id: AllocateMessageQueueAveragelyTeset.java 1831 2013-05-16 01:39:51Z shijia.wxr $ - */ -package com.alibaba.rocketmq.client.consumer.loadbalance; - -import java.util.ArrayList; -import java.util.List; - -import org.junit.Test; - -import com.alibaba.rocketmq.common.MessageQueue; - - -public class AllocateMessageQueueAveragelyTeset { - - @Test - public void test_allocate() { - AllocateMessageQueueAveragely allocateMessageQueueAveragely =new AllocateMessageQueueAveragely(); - String group = "s_test"; - String topic = "topic_test"; - String currentCID = "CID"; - List mqAll = new ArrayList(); - for(int i=0;i<10;i++){ - MessageQueue mq = new MessageQueue(topic,"brokerName",i); - mqAll.add(mq); - } - - List cidAll = new ArrayList (); - for(int j=0;j<3;j++){ - cidAll.add("CID"+j); - } - System.out.println(mqAll.toString()); - System.out.println(cidAll.toString()); - for(int i=0;i<3;i++){ - List rs = allocateMessageQueueAveragely.allocate(group, topic, currentCID+i, mqAll, cidAll); - System.out.println("rs["+currentCID+i+"]:"+rs.toString()); - } - - } -} diff --git a/rocketmq-client/src/test/java/com/alibaba/rocketmq/client/consumer/loadbalance/AllocateMessageQueueAveragelyTest.java b/rocketmq-client/src/test/java/com/alibaba/rocketmq/client/consumer/loadbalance/AllocateMessageQueueAveragelyTest.java new file mode 100644 index 00000000..733aca60 --- /dev/null +++ b/rocketmq-client/src/test/java/com/alibaba/rocketmq/client/consumer/loadbalance/AllocateMessageQueueAveragelyTest.java @@ -0,0 +1,250 @@ +/* + * @author yubao.fyb@taoboa.com + * @version $id$ + */ +package com.alibaba.rocketmq.client.consumer.loadbalance; + +import java.util.ArrayList; +import java.util.List; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import com.alibaba.rocketmq.client.consumer.AllocateMessageQueueStrategy; +import com.alibaba.rocketmq.client.consumer.rebalance.AllocateMessageQueueAveragely; +import com.alibaba.rocketmq.common.message.MessageQueue; + + +/** + * @author yubao.fyb@alibaba-inc.com created on 2013-07-03 16:24 + */ +public class AllocateMessageQueueAveragelyTest { + private AllocateMessageQueueStrategy allocateMessageQueueAveragely; + private String currentCID; + private String topic; + private List messageQueueList; + private List consumerIdList; + + + public void createMessageQueueList(int size) { + messageQueueList = new ArrayList(size); + for (int i = 0; i < size; i++) { + MessageQueue mq = new MessageQueue(topic, "brokerName", i); + messageQueueList.add(mq); + } + } + + + public void createConsumerIdList(int size) { + consumerIdList = new ArrayList(size); + for (int i = 0; i < size; i++) { + consumerIdList.add(String.valueOf(i)); + } + } + + + @Before + public void init() { + allocateMessageQueueAveragely = new AllocateMessageQueueAveragely(); + topic = "topic_test"; + } + + + @Test + public void testConsumer1() { // consumerList大小为1 + currentCID = "0"; + createConsumerIdList(1); + createMessageQueueList(5); + List result = + allocateMessageQueueAveragely.allocate(currentCID, messageQueueList, consumerIdList); + printMessageQueue(result, "testConsumer1"); + Assert.assertEquals(result.size(), 5); + Assert.assertEquals(result.containsAll(getMessageQueueList()), true); + } + + + @Test + public void testConsumer2() { // consumerList大小为2 + currentCID = "1"; + createConsumerIdList(2); + createMessageQueueList(5); + List result = + allocateMessageQueueAveragely.allocate(currentCID, messageQueueList, consumerIdList); + printMessageQueue(result, "testConsumer2"); + Assert.assertEquals(result.size(), 3); + Assert.assertEquals(result.containsAll(getMessageQueueList().subList(2, 5)), true); + + } + + + @Test + public void testConsumer3CurrentCID0() { // consumerList大小为3 + currentCID = "0"; + createConsumerIdList(3); + createMessageQueueList(5); + List result = + allocateMessageQueueAveragely.allocate(currentCID, messageQueueList, consumerIdList); + printMessageQueue(result, "testConsumer3CurrentCID0"); + Assert.assertEquals(result.size(), 1); + Assert.assertEquals(result.containsAll(getMessageQueueList().subList(0, 1)), true); + } + + + @Test + public void testConsumer3CurrentCID1() { // consumerList大小为3 + currentCID = "1"; + createConsumerIdList(3); + createMessageQueueList(5); + List result = + allocateMessageQueueAveragely.allocate(currentCID, messageQueueList, consumerIdList); + printMessageQueue(result, "testConsumer3CurrentCID1"); + Assert.assertEquals(result.size(), 1); + Assert.assertEquals(result.containsAll(getMessageQueueList().subList(1, 2)), true); + } + + + @Test + public void testConsumer3CurrentCID2() { // consumerList大小为3 + currentCID = "2"; + createConsumerIdList(3); + createMessageQueueList(5); + List result = + allocateMessageQueueAveragely.allocate(currentCID, messageQueueList, consumerIdList); + printMessageQueue(result, "testConsumer3CurrentCID2"); + Assert.assertEquals(result.size(), 3); + Assert.assertEquals(result.containsAll(getMessageQueueList().subList(2, 5)), true); + } + + + @Test + public void testConsumer4() { // consumerList大小为4 + currentCID = "1"; + createConsumerIdList(4); + createMessageQueueList(5); + List result = + allocateMessageQueueAveragely.allocate(currentCID, messageQueueList, consumerIdList); + printMessageQueue(result, "testConsumer4"); + Assert.assertEquals(result.size(), 1); + Assert.assertEquals(result.containsAll(getMessageQueueList().subList(1, 2)), true); + } + + + @Test + public void testConsumer5() { // consumerList大小为5 + currentCID = "1"; + createConsumerIdList(5); + createMessageQueueList(5); + List result = + allocateMessageQueueAveragely.allocate(currentCID, messageQueueList, consumerIdList); + printMessageQueue(result, "testConsumer5"); + Assert.assertEquals(result.size(), 1); + Assert.assertEquals(result.containsAll(getMessageQueueList().subList(1, 2)), true); + } + + + @Test + public void testConsumer6() { // consumerList大小为6 + currentCID = "1"; + createConsumerIdList(2); + createMessageQueueList(6); + List result = + allocateMessageQueueAveragely.allocate(currentCID, messageQueueList, consumerIdList); + printMessageQueue(result, "testConsumer"); + Assert.assertEquals(result.size(), 3); + Assert.assertEquals(result.containsAll(getMessageQueueList().subList(3, 6)), true); + } + + + @Test + public void testCurrentCIDNotExists() { // CurrentCID不存在 + currentCID = String.valueOf(Integer.MAX_VALUE); + createConsumerIdList(2); + createMessageQueueList(6); + List result = + allocateMessageQueueAveragely.allocate(currentCID, messageQueueList, consumerIdList); + printMessageQueue(result, "testCurrentCIDNotExists"); + Assert.assertEquals(result.size(), 0); + } + + + @Test(expected = IllegalArgumentException.class) + public void testCurrentCIDIllegalArgument() { // currentCID是空 + createConsumerIdList(2); + createMessageQueueList(6); + allocateMessageQueueAveragely.allocate("", getMessageQueueList(), getConsumerIdList()); + } + + + @Test(expected = IllegalArgumentException.class) + public void testMessageQueueIllegalArgument() { // MessageQueue为空 + currentCID = "0"; + createConsumerIdList(2); + allocateMessageQueueAveragely.allocate(currentCID, null, getConsumerIdList()); + } + + + @Test(expected = IllegalArgumentException.class) + public void testConsumerIdIllegalArgument() { // ConsumerIdList为空 + currentCID = "0"; + createMessageQueueList(6); + allocateMessageQueueAveragely.allocate(currentCID, getMessageQueueList(), null); + } + + + public List getMessageQueueList() { + return messageQueueList; + } + + + public void setMessageQueueList(List messageQueueList) { + this.messageQueueList = messageQueueList; + } + + + public List getConsumerIdList() { + return consumerIdList; + } + + + public void setConsumerIdList(List consumerIdList) { + this.consumerIdList = consumerIdList; + } + + + public void printMessageQueue(List messageQueueList, String name) { + if (messageQueueList == null || messageQueueList.size() < 1) + return; + System.out.println(name + ".......................................start"); + for (MessageQueue messageQueue : messageQueueList) { + System.out.println(messageQueue); + } + System.out.println(name + ".......................................end"); + } + + + @Test + public void testAllocate() { + AllocateMessageQueueAveragely allocateMessageQueueAveragely = new AllocateMessageQueueAveragely(); + String topic = "topic_test"; + String currentCID = "CID"; + int queueSize = 19; + int consumerSize = 10; + List mqAll = new ArrayList(); + for (int i = 0; i < queueSize; i++) { + MessageQueue mq = new MessageQueue(topic, "brokerName", i); + mqAll.add(mq); + } + + List cidAll = new ArrayList(); + for (int j = 0; j < consumerSize; j++) { + cidAll.add("CID" + j); + } + System.out.println(mqAll.toString()); + System.out.println(cidAll.toString()); + for (int i = 0; i < consumerSize; i++) { + List rs = allocateMessageQueueAveragely.allocate(currentCID + i, mqAll, cidAll); + System.out.println("rs[" + currentCID + i + "]:" + rs.toString()); + } + } +} diff --git a/rocketmq-common/pom.xml b/rocketmq-common/pom.xml index 11a21e91..f2f0ce0f 100644 --- a/rocketmq-common/pom.xml +++ b/rocketmq-common/pom.xml @@ -1,14 +1,12 @@ - + com.alibaba.rocketmq rocketmq-all - 3.0.0-SNAPSHOT + 3.0.8-SNAPSHOT 4.0.0 jar - com.alibaba.rocketmq rocketmq-common rocketmq-common ${project.version} @@ -20,17 +18,13 @@ test - ch.qos.logback - logback-classic + ${project.groupId} + rocketmq-remoting - apache-httpclient + commons-httpclient commons-httpclient - - apache-codec - commons-codec - commons-cli commons-cli @@ -39,19 +33,5 @@ commons-io commons-io - - commons-logging - commons-logging - - - com.google.protobuf - protobuf-java - - - - ${project.groupId} - rocketmq-remoting - - diff --git a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/BrokerConfig.java b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/BrokerConfig.java index 6964cdf8..115ba6af 100644 --- a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/BrokerConfig.java +++ b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/BrokerConfig.java @@ -1,5 +1,17 @@ /** - * $Id: BrokerConfig.java 1839 2013-05-16 02:12:02Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.common; @@ -7,49 +19,78 @@ import java.net.InetAddress; import java.net.UnknownHostException; +import com.alibaba.rocketmq.common.annotation.ImportantField; +import com.alibaba.rocketmq.common.constant.PermName; import com.alibaba.rocketmq.remoting.common.RemotingUtil; /** - * + * 服务器配置 * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * @author shijia.wxr */ public class BrokerConfig { - private String rocketmqHome = System.getenv(MixAll.ROCKETMQ_HOME_ENV); - private String namesrvAddr = null; + private String rocketmqHome = System.getProperty(MixAll.ROCKETMQ_HOME_PROPERTY, + System.getenv(MixAll.ROCKETMQ_HOME_ENV)); + @ImportantField + private String namesrvAddr = System.getProperty(MixAll.NAMESRV_ADDR_PROPERTY, + System.getenv(MixAll.NAMESRV_ADDR_ENV)); + @ImportantField private String brokerIP1 = RemotingUtil.getLocalAddress(); private String brokerIP2 = RemotingUtil.getLocalAddress(); + @ImportantField private String brokerName = localHostName(); - private String brokerClusterName = "C01"; + @ImportantField + private String brokerClusterName = "DefaultCluster"; + @ImportantField private long brokerId = MixAll.MASTER_ID; - private int brokerPermission = MixAll.PERM_READ | MixAll.PERM_WRITE; + private int brokerPermission = PermName.PERM_READ | PermName.PERM_WRITE; private int defaultTopicQueueNums = 8; - // ԶTopic - private boolean autoCreateTopic = true; - - // ǷԼȺTopic + // 自动创建Topic功能是否开启(线上建议关闭) + @ImportantField + private boolean autoCreateTopicEnable = true; + // 自动创建以集群名字命名的Topic功能是否开启 private boolean clusterTopicEnable = true; + // 自动创建订阅组功能是否开启(线上建议关闭) + @ImportantField + private boolean autoCreateSubscriptionGroup = true; - private int sendMessageThreadPoolNums = Runtime.getRuntime().availableProcessors() * 6; - private int pullMessageThreadPoolNums = Runtime.getRuntime().availableProcessors() * 6; + private int sendMessageThreadPoolNums = 32 + Runtime.getRuntime().availableProcessors() * 4; + private int pullMessageThreadPoolNums = 32 + Runtime.getRuntime().availableProcessors() * 4; private int adminBrokerThreadPoolNums = 8; private String topicConfigPath = System.getProperty("user.home") + File.separator + "store" - + File.separator + "config" + File.separator + "topics.properties"; + + File.separator + "config" + File.separator + "topics.json"; private String consumerOffsetPath = System.getProperty("user.home") + File.separator + "store" - + File.separator + "config" + File.separator + "consumeroffset.properties"; + + File.separator + "config" + File.separator + "consumerOffset.json"; + + private String brokerConfigPath = System.getProperty("user.home") + File.separator + "store" + + File.separator + "config" + File.separator + "broker.properties"; - private String consumerOffsetHistoryDir = System.getProperty("user.home") + File.separator + "store" - + File.separator + "config" + File.separator + "offsethistory"; + private String subscriptionGroupPath = System.getProperty("user.home") + File.separator + "store" + + File.separator + "config" + File.separator + "subscriptionGroup.json"; private int flushConsumerOffsetInterval = 1000 * 5; private int flushConsumerOffsetHistoryInterval = 1000 * 60; - private String configFilePath = System.getProperty("user.home") + File.separator + "store" - + File.separator + "config" + File.separator + "broker.properties"; + // 查询消息最大时间跨度,单位小时 + private long queryMessageMaxTimeSpan = 24; + + // 是否拒绝接收事务消息 + @ImportantField + private boolean rejectTransactionMessage = false; + + // 是否从地址服务器寻找Name Server地址,正式发布后,默认值为false + @ImportantField + private boolean fetchNamesrvAddrByAddressServer = false; + + // 发送消息对应的线程池阻塞队列size + private int sendThreadPoolQueueCapacity = 100000; + + // 订阅消息对应的线程池阻塞队列size + private int pullThreadPoolQueueCapacity = 100000; public static String localHostName() { @@ -104,13 +145,13 @@ public void setDefaultTopicQueueNums(int defaultTopicQueueNums) { } - public boolean isAutoCreateTopic() { - return autoCreateTopic; + public boolean isAutoCreateTopicEnable() { + return autoCreateTopicEnable; } - public void setAutoCreateTopic(boolean autoCreateTopic) { - this.autoCreateTopic = autoCreateTopic; + public void setAutoCreateTopicEnable(boolean autoCreateTopic) { + this.autoCreateTopicEnable = autoCreateTopic; } @@ -204,16 +245,6 @@ public void setFlushConsumerOffsetInterval(int flushConsumerOffsetInterval) { } - public String getConsumerOffsetHistoryDir() { - return consumerOffsetHistoryDir; - } - - - public void setConsumerOffsetHistoryDir(String consumerOffsetHistoryDir) { - this.consumerOffsetHistoryDir = consumerOffsetHistoryDir; - } - - public int getFlushConsumerOffsetHistoryInterval() { return flushConsumerOffsetHistoryInterval; } @@ -224,13 +255,13 @@ public void setFlushConsumerOffsetHistoryInterval(int flushConsumerOffsetHistory } - public String getConfigFilePath() { - return configFilePath; + public String getBrokerConfigPath() { + return brokerConfigPath; } - public void setConfigFilePath(String configFilePath) { - this.configFilePath = configFilePath; + public void setBrokerConfigPath(String brokerConfigPath) { + this.brokerConfigPath = brokerConfigPath; } @@ -262,4 +293,74 @@ public long getBrokerId() { public void setBrokerId(long brokerId) { this.brokerId = brokerId; } + + + public boolean isAutoCreateSubscriptionGroup() { + return autoCreateSubscriptionGroup; + } + + + public void setAutoCreateSubscriptionGroup(boolean autoCreateSubscriptionGroup) { + this.autoCreateSubscriptionGroup = autoCreateSubscriptionGroup; + } + + + public String getSubscriptionGroupPath() { + return subscriptionGroupPath; + } + + + public void setSubscriptionGroupPath(String subscriptionGroupPath) { + this.subscriptionGroupPath = subscriptionGroupPath; + } + + + public long getQueryMessageMaxTimeSpan() { + return queryMessageMaxTimeSpan; + } + + + public void setQueryMessageMaxTimeSpan(long queryMessageMaxTimeSpan) { + this.queryMessageMaxTimeSpan = queryMessageMaxTimeSpan; + } + + + public boolean isRejectTransactionMessage() { + return rejectTransactionMessage; + } + + + public void setRejectTransactionMessage(boolean rejectTransactionMessage) { + this.rejectTransactionMessage = rejectTransactionMessage; + } + + + public boolean isFetchNamesrvAddrByAddressServer() { + return fetchNamesrvAddrByAddressServer; + } + + + public void setFetchNamesrvAddrByAddressServer(boolean fetchNamesrvAddrByAddressServer) { + this.fetchNamesrvAddrByAddressServer = fetchNamesrvAddrByAddressServer; + } + + + public int getSendThreadPoolQueueCapacity() { + return sendThreadPoolQueueCapacity; + } + + + public void setSendThreadPoolQueueCapacity(int sendThreadPoolQueueCapacity) { + this.sendThreadPoolQueueCapacity = sendThreadPoolQueueCapacity; + } + + + public int getPullThreadPoolQueueCapacity() { + return pullThreadPoolQueueCapacity; + } + + + public void setPullThreadPoolQueueCapacity(int pullThreadPoolQueueCapacity) { + this.pullThreadPoolQueueCapacity = pullThreadPoolQueueCapacity; + } } diff --git a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/ConfigManager.java b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/ConfigManager.java new file mode 100644 index 00000000..c6c79e2c --- /dev/null +++ b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/ConfigManager.java @@ -0,0 +1,80 @@ +/** + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.rocketmq.common; + +import java.io.IOException; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.alibaba.rocketmq.common.constant.LoggerName; + + +/** + * 各种配置的管理接口 + * + * @author shijia.wxr + * @since 2013-6-18 + */ +public abstract class ConfigManager { + private static final Logger plog = LoggerFactory.getLogger(LoggerName.CommonLoggerName); + + + public abstract String encode(); + + + public abstract String encode(final boolean prettyFormat); + + + public abstract void decode(final String jsonString); + + + public abstract String configFilePath(); + + + public boolean load() { + String fileName = null; + try { + fileName = this.configFilePath(); + String jsonString = MixAll.file2String(fileName); + if (jsonString != null) { + this.decode(jsonString); + plog.info("load " + fileName + " OK"); + return true; + } + } + catch (Exception e) { + plog.error("load " + fileName + " Failed", e); + return false; + } + + return true; + } + + + public synchronized void persist() { + String jsonString = this.encode(true); + if (jsonString != null) { + String fileName = this.configFilePath(); + try { + MixAll.string2File(jsonString, fileName); + } + catch (IOException e) { + plog.error("persist file Exception, " + fileName, e); + } + } + } +} diff --git a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/DataVersion.java b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/DataVersion.java index b2abcdfe..b5bc747e 100644 --- a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/DataVersion.java +++ b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/DataVersion.java @@ -1,44 +1,64 @@ /** - * $Id: DataVersion.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.common; import java.util.concurrent.atomic.AtomicLong; +import com.alibaba.rocketmq.remoting.protocol.RemotingSerializable; + /** - * ʶݵİ汾 - * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * 用来标识数据的版本号 * + * @author shijia.wxr */ -public class DataVersion { +public class DataVersion extends RemotingSerializable { private long timestatmp = System.currentTimeMillis(); private AtomicLong counter = new AtomicLong(0); - public String encode() { - return this.timestatmp + " " + this.counter.get(); + public void assignNewOne(final DataVersion dataVersion) { + this.timestatmp = dataVersion.timestatmp; + this.counter.set(dataVersion.counter.get()); } - public static DataVersion decode(final String data) { - String[] strs = data.split(" "); - DataVersion dv = new DataVersion(); - dv.timestatmp = Long.parseLong(strs[0]); - dv.counter.set(Long.parseLong(strs[1])); - return dv; + public void nextVersion() { + this.timestatmp = System.currentTimeMillis(); + this.counter.incrementAndGet(); } - public String nextVersion() { - this.counter.incrementAndGet(); - return this.encode(); + public long getTimestatmp() { + return timestatmp; + } + + + public void setTimestatmp(long timestatmp) { + this.timestatmp = timestatmp; + } + + + public AtomicLong getCounter() { + return counter; } - public String currentVersion() { - return this.encode(); + public void setCounter(AtomicLong counter) { + this.counter = counter; } diff --git a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/MQVersion.java b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/MQVersion.java index 6a26784a..266b0d10 100644 --- a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/MQVersion.java +++ b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/MQVersion.java @@ -1,17 +1,57 @@ +/** + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package com.alibaba.rocketmq.common; /** - * 汾Ϣ + * 定义各个版本信息 * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * @author shijia.wxr */ public class MQVersion { - // TODO ÿη汾Ҫ޸Ĵ˴汾 - public static final int CurrentVersion = Version.V3_0_0_SNAPSHOT.ordinal(); + // TODO 每次发布版本都要修改此处版本号 + public static final int CurrentVersion = Version.V3_0_8_SNAPSHOT.ordinal(); + + + public static String getVersionDesc(int value) { + Version v = Version.values()[value]; + return v.name(); + } + + + public static Version value2Version(int value) { + return Version.values()[value]; + } - enum Version { + public static enum Version { V3_0_0_SNAPSHOT, - V3_0_0, + V3_0_0_ALPHA1, + V3_0_0_BETA1, + V3_0_0_BETA2, + V3_0_0_BETA3, + V3_0_0_BETA4, + V3_0_0_BETA5, + V3_0_0_BETA6_SNAPSHOT, + V3_0_0_BETA6, + V3_0_0_BETA7_SNAPSHOT, + V3_0_0_BETA7, + V3_0_0_BETA8_SNAPSHOT, + V3_0_0_BETA8, + V3_0_0_BETA9_SNAPSHOT, + V3_0_0_BETA9, + V3_0_0_FINAL, V3_0_1_SNAPSHOT, V3_0_1, V3_0_2_SNAPSHOT, @@ -20,16 +60,31 @@ enum Version { V3_0_3, V3_0_4_SNAPSHOT, V3_0_4, - } + V3_0_5_SNAPSHOT, + V3_0_5, + V3_0_6_SNAPSHOT, + V3_0_6, + V3_0_7_SNAPSHOT, + V3_0_7, + V3_0_8_SNAPSHOT, + V3_0_8, + V3_0_9_SNAPSHOT, + V3_0_9, + V3_0_10_SNAPSHOT, + V3_0_10, + V3_0_11_SNAPSHOT, + V3_0_11, + V3_0_12_SNAPSHOT, + V3_0_12, - public static String getVersionDesc(int value) { - Version v = Version.values()[value]; - return v.name(); - } + V3_0_13_SNAPSHOT, + V3_0_13, + V3_0_14_SNAPSHOT, + V3_0_14, - public static Version value2Version(int value) { - return Version.values()[value]; + V3_0_15_SNAPSHOT, + V3_0_15, } } diff --git a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/MessageId.java b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/MessageId.java deleted file mode 100644 index 40770b2e..00000000 --- a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/MessageId.java +++ /dev/null @@ -1,54 +0,0 @@ -/** - * $Id: MessageId.java 1831 2013-05-16 01:39:51Z shijia.wxr $ - */ -package com.alibaba.rocketmq.common; - -import java.net.SocketAddress; - - -/** - * @author vintage.wang@gmail.com shijia.wxr@taobao.com - * - */ -public class MessageId { - private long timestamp; - private SocketAddress address; - private long offset; - - - public MessageId(long timestamp, SocketAddress address, long offset) { - this.timestamp = timestamp; - this.address = address; - this.offset = offset; - } - - - public long getTimestamp() { - return timestamp; - } - - - public void setTimestamp(long timestamp) { - this.timestamp = timestamp; - } - - - public SocketAddress getAddress() { - return address; - } - - - public void setAddress(SocketAddress address) { - this.address = address; - } - - - public long getOffset() { - return offset; - } - - - public void setOffset(long offset) { - this.offset = offset; - } -} diff --git a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/MixAll.java b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/MixAll.java index 0311e353..54c2c2cf 100644 --- a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/MixAll.java +++ b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/MixAll.java @@ -1,3 +1,18 @@ +/** + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package com.alibaba.rocketmq.common; import java.io.ByteArrayInputStream; @@ -7,6 +22,7 @@ import java.io.IOException; import java.io.InputStream; import java.io.UnsupportedEncodingException; +import java.lang.annotation.Annotation; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.lang.reflect.Modifier; @@ -19,9 +35,11 @@ import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.Enumeration; +import java.util.HashSet; import java.util.List; import java.util.Properties; import java.util.Set; +import java.util.concurrent.atomic.AtomicLong; import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.CommandLineParser; @@ -31,46 +49,53 @@ import org.apache.commons.cli.ParseException; import org.apache.commons.io.IOUtils; import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import sun.management.ManagementFactory; - -import com.sun.management.OperatingSystemMXBean; +import com.alibaba.rocketmq.common.annotation.ImportantField; /** - * ַӻ + * 各种方法大杂烩 * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * @author shijia.wxr * @author lansheng.zj@taobao.com - * */ public class MixAll { - public static final int PERM_PRIORITY = 0x1 << 3; - public static final int PERM_READ = 0x1 << 2; - public static final int PERM_WRITE = 0x1 << 1; - public static final int PERM_INHERIT = 0x1 << 0; - public static final String ROCKETMQ_HOME_ENV = "ROCKETMQ_HOME"; - public static final String WS_DOMAIN_NAME = "diamondserver.tbsite.net"; - // http://diamondserver.tbsite.net:8080/metaq/nsaddr - public static final String WS_ADDR = "http://" + WS_DOMAIN_NAME + ":8080/metaq/nsaddr"; + public static final String ROCKETMQ_HOME_PROPERTY = "rocketmq.home.dir"; + public static final String NAMESRV_ADDR_ENV = "NAMESRV_ADDR"; + public static final String NAMESRV_ADDR_PROPERTY = "rocketmq.namesrv.addr"; + public static final String WS_DOMAIN_NAME = System.getProperty("rocketmq.namesrv.domain", + "jmenv.tbsite.net"); + public static final String MESSAGE_COMPRESS_LEVEL = "rocketmq.message.compressLevel"; + // http://jmenv.tbsite.net:8080/rocketmq/nsaddr + public static final String WS_ADDR = "http://" + WS_DOMAIN_NAME + ":8080/rocketmq/nsaddr"; public static final String DEFAULT_TOPIC = "TBW102"; + public static final String BENCHMARK_TOPIC = "BenchmarkTest"; public static final String DEFAULT_PRODUCER_GROUP = "DEFAULT_PRODUCER"; public static final String DEFAULT_CONSUMER_GROUP = "DEFAULT_CONSUMER"; + public static final String TOOLS_CONSUMER_GROUP = "TOOLS_CONSUMER"; + public static final String CLIENT_INNER_PRODUCER_GROUP = "CLIENT_INNER_PRODUCER"; public static final String SELF_TEST_TOPIC = "SELF_TEST_TOPIC"; - public static final String NamesrvLoggerName = "RocketmqNamesrv"; - public static final String BrokerLoggerName = "RocketmqBroker"; - public static final String ClientLoggerName = "RocketmqClient"; - public static final String ToolsLoggerName = "RocketmqTools"; - public static final String CommonLoggerName = "RocketmqCommon"; - public static final String StoreLoggerName = "RocketmqStore"; - public static final long TotalPhysicalMemorySize = getTotalPhysicalMemorySize(); + public static final List LocalInetAddrs = getLocalInetAddress(); public static final String Localhost = localhost(); public static final String DEFAULT_CHARSET = "UTF-8"; public static final long MASTER_ID = 0L; public static final long CURRENT_JVM_PID = getPID(); + // 为每个Consumer Group建立一个默认的Topic,前缀 + GroupName,用来保存处理失败需要重试的消息 + public static final String RETRY_GROUP_TOPIC_PREFIX = "%RETRY%"; + // 为每个Consumer Group建立一个默认的Topic,前缀 + GroupName,用来保存重试多次都失败,接下来不再重试的消息 + public static final String DLQ_GROUP_TOPIC_PREFIX = "%DLQ%"; + + + public static String getRetryTopic(final String consumerGroup) { + return RETRY_GROUP_TOPIC_PREFIX + consumerGroup; + } + + + public static String getDLQTopic(final String consumerGroup) { + return DLQ_GROUP_TOPIC_PREFIX + consumerGroup; + } public static long getPID() { @@ -88,39 +113,6 @@ public static long getPID() { } - public static final String file2String(final String fileName) { - File file = new File(fileName); - char[] data = new char[(int) file.length()]; - boolean result = false; - - FileReader fileReader = null; - try { - fileReader = new FileReader(file); - int len = fileReader.read(data); - result = (len == data.length); - } - catch (IOException e) { - // e.printStackTrace(); - } - finally { - if (fileReader != null) - try { - fileReader.close(); - } - catch (IOException e) { - e.printStackTrace(); - } - } - - if (result) { - String value = new String(data); - return value; - } - - return null; - } - - public static long createBrokerId(final String ip, final int port) { InetSocketAddress isa = new InetSocketAddress(ip, port); byte[] ipArray = isa.getAddress().getAddress(); @@ -132,7 +124,32 @@ public static long createBrokerId(final String ip, final int port) { } - public static final boolean string2File(final String str, final String fileName) { + /** + * 安全的写文件 + */ + public static final void string2File(final String str, final String fileName) throws IOException { + // 先写入临时文件 + String tmpFile = fileName + ".tmp"; + string2FileNotSafe(str, tmpFile); + + // 备份之前的文件 + String bakFile = fileName + ".bak"; + String prevContent = file2String(fileName); + if (prevContent != null) { + string2FileNotSafe(prevContent, bakFile); + } + + // 删除正式文件 + File file = new File(fileName); + file.delete(); + + // 临时文件改为正式文件 + file = new File(tmpFile); + file.renameTo(new File(fileName)); + } + + + public static final void string2FileNotSafe(final String str, final String fileName) throws IOException { File file = new File(fileName); File fileParent = file.getParentFile(); if (fileParent != null) { @@ -143,55 +160,55 @@ public static final boolean string2File(final String str, final String fileName) try { fileWriter = new FileWriter(file); fileWriter.write(str); - return true; } catch (IOException e) { - e.printStackTrace(); + throw e; } finally { - if (fileWriter != null) + if (fileWriter != null) { try { fileWriter.close(); } catch (IOException e) { - e.printStackTrace(); + throw e; } + } } - - return false; } - public static boolean isReadable(final int perm) { - return (perm & PERM_READ) == PERM_READ; - } - - - public static boolean isWriteable(final int perm) { - return (perm & PERM_WRITE) == PERM_WRITE; - } - - - public static boolean isInherited(final int perm) { - return (perm & PERM_INHERIT) == PERM_INHERIT; - } - - - public static String perm2String(final int perm) { - final StringBuffer sb = new StringBuffer("---"); - if (isReadable(perm)) { - sb.replace(0, 1, "R"); - } + public static final String file2String(final String fileName) { + File file = new File(fileName); + if (file.exists()) { + char[] data = new char[(int) file.length()]; + boolean result = false; - if (isWriteable(perm)) { - sb.replace(1, 2, "W"); - } + FileReader fileReader = null; + try { + fileReader = new FileReader(file); + int len = fileReader.read(data); + result = (len == data.length); + } + catch (IOException e) { + // e.printStackTrace(); + } + finally { + if (fileReader != null) { + try { + fileReader.close(); + } + catch (IOException e) { + e.printStackTrace(); + } + } + } - if (isInherited(perm)) { - sb.replace(2, 3, "X"); + if (result) { + String value = new String(data); + return value; + } } - - return sb.toString(); + return null; } @@ -236,6 +253,13 @@ public static CommandLine parseCmdLine(final String appName, String[] args, Opti } + public static void printCommandLineHelp(final String appName, final Options options) { + HelpFormatter hf = new HelpFormatter(); + hf.setWidth(110); + hf.printHelp(appName, options, true); + } + + public static Properties commandLine2Properties(final CommandLine commandLine) { Properties properties = new Properties(); Option[] opts = commandLine.getOptions(); @@ -255,6 +279,12 @@ public static Properties commandLine2Properties(final CommandLine commandLine) { public static void printObjectProperties(final Logger log, final Object object) { + printObjectProperties(log, object, false); + } + + + public static void printObjectProperties(final Logger log, final Object object, + final boolean onlyImportantField) { Field[] fields = object.getClass().getDeclaredFields(); for (Field field : fields) { if (!Modifier.isStatic(field.getModifiers())) { @@ -274,6 +304,14 @@ public static void printObjectProperties(final Logger log, final Object object) catch (IllegalAccessException e) { System.out.println(e); } + + if (onlyImportantField) { + Annotation annotation = field.getAnnotation(ImportantField.class); + if (null == annotation) { + continue; + } + } + if (log != null) { log.info(name + "=" + value); } @@ -286,18 +324,6 @@ public static void printObjectProperties(final Logger log, final Object object) } - /** - * ȡڴ - * - * @return λֽ - */ - public static long getTotalPhysicalMemorySize() { - OperatingSystemMXBean osmxb = (OperatingSystemMXBean) ManagementFactory.getOperatingSystemMXBean(); - long physicalTotal = osmxb.getTotalPhysicalMemorySize(); - return physicalTotal; - } - - public static String properties2String(final Properties properties) { Set sets = properties.keySet(); StringBuilder sb = new StringBuilder(); @@ -313,7 +339,7 @@ public static String properties2String(final Properties properties) { /** - * ַתProperties ַPropertiesļʽһ + * 字符串转化成Properties 字符串和Properties配置文件格式一样 */ public static Properties string2Properties(final String str) { Properties properties = new Properties(); @@ -335,7 +361,7 @@ public static Properties string2Properties(final String str) { /** - * ԱֵתΪProperties + * 将对象各成员属性值转化为Properties */ public static Properties object2Properties(final Object object) { Properties properties = new Properties(); @@ -369,7 +395,7 @@ public static Properties object2Properties(final Object object) { /** - * PropertiesеֵдObject + * 将Properties中的值写入Object */ public static void properties2Object(final Properties p, final Object object) { Method[] methods = object.getClass().getMethods(); @@ -421,12 +447,6 @@ public static boolean isPropertiesEqual(final Properties p1, final Properties p2 } - public static Logger createLogger(final String file, final String level) { - // TODO - return LoggerFactory.getLogger(ClientLoggerName); - } - - public static List getLocalInetAddress() { List inetAddressList = new ArrayList(); try { @@ -466,4 +486,35 @@ private static String localhost() { } } + + public static boolean compareAndIncreaseOnly(final AtomicLong target, final long value) { + long prev = target.get(); + while (value > prev) { + boolean updated = target.compareAndSet(prev, value); + if (updated) + return true; + + prev = target.get(); + } + + return false; + } + + + public Set list2Set(List values) { + Set result = new HashSet(); + for (String v : values) { + result.add(v); + } + return result; + } + + + public List set2List(Set values) { + List result = new ArrayList(); + for (String v : values) { + result.add(v); + } + return result; + } } diff --git a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/Pair.java b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/Pair.java index 0ca939fb..f93d4beb 100644 --- a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/Pair.java +++ b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/Pair.java @@ -1,11 +1,22 @@ /** - * $Id: Pair.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.common; /** - * @author vintage.wang@gmail.com shijia.wxr@taobao.com - * + * @author shijia.wxr */ public class Pair { private T1 object1; diff --git a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/ServiceState.java b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/ServiceState.java index f12be485..4fc02241 100644 --- a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/ServiceState.java +++ b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/ServiceState.java @@ -1,16 +1,40 @@ /** - * $Id: ServiceState.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.common; /** - * ״̬ͨҪstartshutdown - * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * 服务对象的状态,通常需要start,shutdown * + * @author shijia.wxr */ public enum ServiceState { + /** + * 服务对象刚刚创建,但是未启动 + */ CREATE_JUST, + /** + * 服务启动成功 + */ RUNNING, - SHUTDOWN_ALREADY + /** + * 服务已经关闭 + */ + SHUTDOWN_ALREADY, + /** + * 服务启动失败 + */ + START_FAILED } diff --git a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/ServiceThread.java b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/ServiceThread.java index 2fb4d9ca..094273df 100644 --- a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/ServiceThread.java +++ b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/ServiceThread.java @@ -1,26 +1,40 @@ /** - * $Id: ServiceThread.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.common; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.alibaba.rocketmq.common.constant.LoggerName; + /** - * ̨̻߳ + * 后台服务线程基类 * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * @author shijia.wxr */ public abstract class ServiceThread implements Runnable { - private static final Logger stlog = LoggerFactory.getLogger(MixAll.CommonLoggerName); - // ִ߳ + private static final Logger stlog = LoggerFactory.getLogger(LoggerName.CommonLoggerName); + // 执行线程 protected final Thread thread; - // ̻߳ʱ䣬Ĭ90S + // 线程回收时间,默认90S private static final long JoinTime = 90 * 1000; - // ǷѾNotify + // 是否已经被Notify过 protected volatile boolean hasNotified = false; - // ߳ǷѾֹͣ + // 线程是否已经停止 protected volatile boolean stoped = false; diff --git a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/SubGroupConfig.java b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/SubGroupConfig.java deleted file mode 100644 index 1ea88f5d..00000000 --- a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/SubGroupConfig.java +++ /dev/null @@ -1,52 +0,0 @@ -/** - * $Id: SubGroupConfig.java 1831 2013-05-16 01:39:51Z shijia.wxr $ - */ -package com.alibaba.rocketmq.common; - -/** - * - * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com - */ -public class SubGroupConfig { - private String groupName; - // 0 ʾ master - // > 0 ʾ slave - private int subFromWhere = 0; - private int perm = MixAll.PERM_READ; - - - public SubGroupConfig(String groupName) { - this.groupName = groupName; - } - - - public String getGroupName() { - return groupName; - } - - - public void setGroupName(String groupName) { - this.groupName = groupName; - } - - - public int getSubFromWhere() { - return subFromWhere; - } - - - public void setSubFromWhere(int subFromWhere) { - this.subFromWhere = subFromWhere; - } - - - public int getPerm() { - return perm; - } - - - public void setPerm(int perm) { - this.perm = perm; - } -} diff --git a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/SystemClock.java b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/SystemClock.java index 4496ef16..c1cc94df 100644 --- a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/SystemClock.java +++ b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/SystemClock.java @@ -1,5 +1,17 @@ /** - * $Id: SystemClock.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.common; @@ -11,12 +23,12 @@ /** - * ̨ʱʱӣJVM˳ʱ߳Զ + * 后台定时更新时钟,JVM退出时,线程自动回收 * + * @author vintage.wang@gmail.com shijia.wxr@taobao.com * @see * https://github.com/zhongl/jtoolkit/blob/master/common/src/main/java/com * /github/zhongl/jtoolkit/SystemClock.java - * @author vintage.wang@gmail.com shijia.wxr@taobao.com */ public class SystemClock { diff --git a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/TopicConfig.java b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/TopicConfig.java index 33c71294..fa568bd1 100644 --- a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/TopicConfig.java +++ b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/TopicConfig.java @@ -1,12 +1,27 @@ /** - * $Id: TopicConfig.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.common; +import com.alibaba.rocketmq.common.constant.PermName; + + /** - * Topic + * Topic配置 * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * @author shijia.wxr */ public class TopicConfig { public static int DefaultReadQueueNums = 16; @@ -17,8 +32,12 @@ public class TopicConfig { private String topicName; private int readQueueNums = DefaultReadQueueNums; private int writeQueueNums = DefaultWriteQueueNums; - private int perm = MixAll.PERM_READ | MixAll.PERM_WRITE; - private TopicFilterType topicFilterType = TopicFilterType.MULTI_TAG; + private int perm = PermName.PERM_READ | PermName.PERM_WRITE; + private TopicFilterType topicFilterType = TopicFilterType.SINGLE_TAG; + + + public TopicConfig() { + } public TopicConfig(String topicName) { @@ -145,8 +164,8 @@ public boolean equals(Object obj) { @Override public String toString() { - return "TopicConfig [topicName=" + topicName + ", readQueueNums=" + readQueueNums + ", writeQueueNums=" - + writeQueueNums + ", perm=" + MixAll.perm2String(perm) + ", topicFilterType=" + topicFilterType - + "]"; + return "TopicConfig [topicName=" + topicName + ", readQueueNums=" + readQueueNums + + ", writeQueueNums=" + writeQueueNums + ", perm=" + PermName.perm2String(perm) + + ", topicFilterType=" + topicFilterType + "]"; } } diff --git a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/TopicFilterType.java b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/TopicFilterType.java index 8e147ee9..7adbb584 100644 --- a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/TopicFilterType.java +++ b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/TopicFilterType.java @@ -1,21 +1,34 @@ /** - * $Id: TopicFilterType.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.common; /** - * Topic˷ʽĬΪTAG - * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * Topic过滤方式,默认为单TAG过滤 * + * @author shijia.wxr */ public enum TopicFilterType { /** - * ÿϢֻһTag + * 每个消息只能有一个Tag */ SINGLE_TAG, /** - * ÿϢжTag + * 每个消息可以有多个Tag(暂时不支持,后续视情况支持)
+ * 为什么暂时不支持?
+ * 此功能可能会对用户造成困扰,且方案并不完美,所以暂不支持 */ MULTI_TAG } diff --git a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/UtilALl.java b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/UtilAll.java similarity index 70% rename from rocketmq-common/src/main/java/com/alibaba/rocketmq/common/UtilALl.java rename to rocketmq-common/src/main/java/com/alibaba/rocketmq/common/UtilAll.java index 60afbe40..4fe4ce40 100644 --- a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/UtilALl.java +++ b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/UtilAll.java @@ -1,3 +1,18 @@ +/** + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package com.alibaba.rocketmq.common; import java.io.ByteArrayInputStream; @@ -20,11 +35,16 @@ /** - * ַӻ + * 各种方法大杂烩 * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * @author shijia.wxr */ -public class UtilALl { +public class UtilAll { + public static final String yyyy_MM_dd_HH_mm_ss = "yyyy-MM-dd HH:mm:ss"; + public static final String yyyy_MM_dd_HH_mm_ss_SSS = "yyyy-MM-dd#HH:mm:ss:SSS"; + public static final String yyyyMMddHHmmss = "yyyyMMddHHmmss"; + + public static int getPid() { RuntimeMXBean runtime = ManagementFactory.getRuntimeMXBean(); String name = runtime.getName(); // format: "pid@hostname" @@ -38,8 +58,8 @@ public static int getPid() { /** - * offsetתַʽ
- * 20λ + * 将offset转化成字符串形式
+ * 左补零对齐至20位 */ public static String offset2FileName(final long offset) { final NumberFormat nf = NumberFormat.getInstance(); @@ -51,7 +71,7 @@ public static String offset2FileName(final long offset) { /** - * ʱλms + * 计算耗时操作,单位ms */ public static long computeEclipseTimeMilliseconds(final long beginTime) { return (System.currentTimeMillis() - beginTime); @@ -82,14 +102,61 @@ public static String timeMillisToHumanString() { public static String timeMillisToHumanString(final long t) { Calendar cal = Calendar.getInstance(); cal.setTimeInMillis(t); - return String.format("%04d%02d%02d%02d%02d%02d%03d", cal.get(Calendar.YEAR), cal.get(Calendar.MONTH) + 1, - cal.get(Calendar.DAY_OF_MONTH), cal.get(Calendar.HOUR_OF_DAY), cal.get(Calendar.MINUTE), - cal.get(Calendar.SECOND), cal.get(Calendar.MILLISECOND)); + return String.format("%04d%02d%02d%02d%02d%02d%03d", cal.get(Calendar.YEAR), + cal.get(Calendar.MONTH) + 1, cal.get(Calendar.DAY_OF_MONTH), cal.get(Calendar.HOUR_OF_DAY), + cal.get(Calendar.MINUTE), cal.get(Calendar.SECOND), cal.get(Calendar.MILLISECOND)); + } + + + public static long computNextMorningTimeMillis() { + Calendar cal = Calendar.getInstance(); + cal.setTimeInMillis(System.currentTimeMillis()); + cal.add(Calendar.DAY_OF_MONTH, 1); + cal.set(Calendar.HOUR_OF_DAY, 0); + cal.set(Calendar.MINUTE, 0); + cal.set(Calendar.SECOND, 0); + cal.set(Calendar.MILLISECOND, 0); + + return cal.getTimeInMillis(); + } + + + public static String timeMillisToHumanString2(final long t) { + Calendar cal = Calendar.getInstance(); + cal.setTimeInMillis(t); + return String.format("%04d-%02d-%02d %02d:%02d:%02d,%03d",// + cal.get(Calendar.YEAR),// + cal.get(Calendar.MONTH) + 1,// + cal.get(Calendar.DAY_OF_MONTH),// + cal.get(Calendar.HOUR_OF_DAY),// + cal.get(Calendar.MINUTE),// + cal.get(Calendar.SECOND),// + cal.get(Calendar.MILLISECOND)); + } + + + /** + * 返回日期时间格式,精度到秒
+ * 格式如下:2013122305190000 + * + * @param t + * @return + */ + public static String timeMillisToHumanString3(final long t) { + Calendar cal = Calendar.getInstance(); + cal.setTimeInMillis(t); + return String.format("%04d%02d%02d%02d%02d%02d",// + cal.get(Calendar.YEAR),// + cal.get(Calendar.MONTH) + 1,// + cal.get(Calendar.DAY_OF_MONTH),// + cal.get(Calendar.HOUR_OF_DAY),// + cal.get(Calendar.MINUTE),// + cal.get(Calendar.SECOND)); } /** - * ȡ̷ռʹ + * 获取磁盘分区空间使用率 */ public static double getDiskPartitionSpaceUsedPercent(final String path) { if (null == path || path.isEmpty()) @@ -136,10 +203,10 @@ public static final int crc32(byte[] array, int offset, int length) { /** - * ֽת16ʽ + * 字节数组转化成16进制形式 */ public static String bytes2string(byte[] src) { - StringBuilder sb = new StringBuilder(40); + StringBuilder sb = new StringBuilder(); if (src == null || src.length <= 0) { return null; } @@ -156,7 +223,7 @@ public static String bytes2string(byte[] src) { /** - * 16ַתֽ + * 16进制字符串转化成字节数组 */ public static byte[] string2bytes(String hexString) { if (hexString == null || hexString.equals("")) { @@ -270,9 +337,6 @@ public static long asLong(String str, long defaultValue) { } } - public static final String yyyy_MM_dd_HH_mm_ss = "yyyy-MM-dd HH:mm:ss"; - public static final String yyyyMMddHHmmss = "yyyyMMddHHmmss"; - public static String formatDate(Date date, String pattern) { SimpleDateFormat df = new SimpleDateFormat(pattern); @@ -304,4 +368,29 @@ public static String responseCode2String(final int code) { return null; } + + + public static String frontStringAtLeast(final String str, final int size) { + if (str != null) { + if (str.length() > size) { + return str.substring(0, size); + } + } + + return str; + } + + + public static boolean isBlank(String str) { + int strLen; + if (str == null || (strLen = str.length()) == 0) { + return true; + } + for (int i = 0; i < strLen; i++) { + if (Character.isWhitespace(str.charAt(i))) { + return true; + } + } + return false; + } } diff --git a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/admin/ConsumeStats.java b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/admin/ConsumeStats.java new file mode 100644 index 00000000..d952f213 --- /dev/null +++ b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/admin/ConsumeStats.java @@ -0,0 +1,69 @@ +/** + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.rocketmq.common.admin; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map.Entry; + +import com.alibaba.rocketmq.common.message.MessageQueue; +import com.alibaba.rocketmq.remoting.protocol.RemotingSerializable; + + +/** + * Consumer消费进度 + * + * @author shijia.wxr + * @since 2013-7-14 + */ +public class ConsumeStats extends RemotingSerializable { + private HashMap offsetTable = new HashMap(); + private long consumeTps = 0; + + + public long computeTotalDiff() { + long diffTotal = 0L; + + Iterator> it = this.offsetTable.entrySet().iterator(); + while (it.hasNext()) { + Entry next = it.next(); + long diff = next.getValue().getBrokerOffset() - next.getValue().getConsumerOffset(); + diffTotal += diff; + } + + return diffTotal; + } + + + public HashMap getOffsetTable() { + return offsetTable; + } + + + public void setOffsetTable(HashMap offsetTable) { + this.offsetTable = offsetTable; + } + + + public long getConsumeTps() { + return consumeTps; + } + + + public void setConsumeTps(long consumeTps) { + this.consumeTps = consumeTps; + } +} diff --git a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/admin/OffsetWrapper.java b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/admin/OffsetWrapper.java new file mode 100644 index 00000000..65a95efa --- /dev/null +++ b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/admin/OffsetWrapper.java @@ -0,0 +1,59 @@ +/** + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.rocketmq.common.admin; + +/** + * Offset包装类,含Broker、Consumer + * + * @author shijia.wxr + * @since 2013-7-14 + */ +public class OffsetWrapper { + private long brokerOffset; + private long consumerOffset; + // 消费的最后一条消息对应的时间戳 + private long lastTimestamp; + + + public long getBrokerOffset() { + return brokerOffset; + } + + + public void setBrokerOffset(long brokerOffset) { + this.brokerOffset = brokerOffset; + } + + + public long getConsumerOffset() { + return consumerOffset; + } + + + public void setConsumerOffset(long consumerOffset) { + this.consumerOffset = consumerOffset; + } + + + public long getLastTimestamp() { + return lastTimestamp; + } + + + public void setLastTimestamp(long lastTimestamp) { + this.lastTimestamp = lastTimestamp; + } +} diff --git a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/admin/RollbackStats.java b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/admin/RollbackStats.java new file mode 100644 index 00000000..caeba709 --- /dev/null +++ b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/admin/RollbackStats.java @@ -0,0 +1,76 @@ +package com.alibaba.rocketmq.common.admin; + +/** + * 按时间回溯消费进度 + * + * @author: manhong.yqd + * @since: 13-9-12 + */ +public class RollbackStats { + private String brokerName; + private long queueId; + private long brokerOffset; + private long consumerOffset; + private long timestampOffset; + private long rollbackOffset; + + + public String getBrokerName() { + return brokerName; + } + + + public void setBrokerName(String brokerName) { + this.brokerName = brokerName; + } + + + public long getQueueId() { + return queueId; + } + + + public void setQueueId(long queueId) { + this.queueId = queueId; + } + + + public long getBrokerOffset() { + return brokerOffset; + } + + + public void setBrokerOffset(long brokerOffset) { + this.brokerOffset = brokerOffset; + } + + + public long getConsumerOffset() { + return consumerOffset; + } + + + public void setConsumerOffset(long consumerOffset) { + this.consumerOffset = consumerOffset; + } + + + public long getTimestampOffset() { + return timestampOffset; + } + + + public void setTimestampOffset(long timestampOffset) { + this.timestampOffset = timestampOffset; + } + + + public long getRollbackOffset() { + return rollbackOffset; + } + + + public void setRollbackOffset(long rollbackOffset) { + this.rollbackOffset = rollbackOffset; + } +} diff --git a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/admin/TopicOffset.java b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/admin/TopicOffset.java new file mode 100644 index 00000000..02689db7 --- /dev/null +++ b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/admin/TopicOffset.java @@ -0,0 +1,58 @@ +/** + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.rocketmq.common.admin; + +/** + * Topic 统计信息信息 + * + * @author shijia.wxr + * @since 2013-7-14 + */ +public class TopicOffset { + private long minOffset; + private long maxOffset; + private long lastUpdateTimestamp; + + + public long getMinOffset() { + return minOffset; + } + + + public void setMinOffset(long minOffset) { + this.minOffset = minOffset; + } + + + public long getMaxOffset() { + return maxOffset; + } + + + public void setMaxOffset(long maxOffset) { + this.maxOffset = maxOffset; + } + + + public long getLastUpdateTimestamp() { + return lastUpdateTimestamp; + } + + + public void setLastUpdateTimestamp(long lastUpdateTimestamp) { + this.lastUpdateTimestamp = lastUpdateTimestamp; + } +} diff --git a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/admin/TopicStatsTable.java b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/admin/TopicStatsTable.java new file mode 100644 index 00000000..1e8217d6 --- /dev/null +++ b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/admin/TopicStatsTable.java @@ -0,0 +1,42 @@ +/** + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.rocketmq.common.admin; + +import java.util.HashMap; + +import com.alibaba.rocketmq.common.message.MessageQueue; +import com.alibaba.rocketmq.remoting.protocol.RemotingSerializable; + + +/** + * Topic所有队列的Offset + * + * @author shijia.wxr + * @since 2013-7-14 + */ +public class TopicStatsTable extends RemotingSerializable { + private HashMap offsetTable = new HashMap(); + + + public HashMap getOffsetTable() { + return offsetTable; + } + + + public void setOffsetTable(HashMap offsetTable) { + this.offsetTable = offsetTable; + } +} diff --git a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/annotation/ImportantField.java b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/annotation/ImportantField.java new file mode 100644 index 00000000..525cb4bf --- /dev/null +++ b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/annotation/ImportantField.java @@ -0,0 +1,29 @@ +/** + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.rocketmq.common.annotation; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + + +@Documented +@Retention(RetentionPolicy.RUNTIME) +@Target({ ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.LOCAL_VARIABLE }) +public @interface ImportantField { +} diff --git a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/constant/LoggerName.java b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/constant/LoggerName.java new file mode 100644 index 00000000..6949ce35 --- /dev/null +++ b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/constant/LoggerName.java @@ -0,0 +1,30 @@ +/** + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.rocketmq.common.constant; + +/** + * @author shijia.wxr + */ +public class LoggerName { + public static final String NamesrvLoggerName = "RocketmqNamesrv"; + public static final String BrokerLoggerName = "RocketmqBroker"; + public static final String ClientLoggerName = "RocketmqClient"; + public static final String ToolsLoggerName = "RocketmqTools"; + public static final String CommonLoggerName = "RocketmqCommon"; + public static final String StoreLoggerName = "RocketmqStore"; + public static final String TransactionLoggerName = "RocketmqTransaction"; + public static final String RebalanceLockLoggerName = "RocketmqRebalanceLock"; +} diff --git a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/constant/PermName.java b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/constant/PermName.java new file mode 100644 index 00000000..a43435e4 --- /dev/null +++ b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/constant/PermName.java @@ -0,0 +1,59 @@ +/** + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.rocketmq.common.constant; + +/** + * @author shijia.wxr + */ +public class PermName { + public static final int PERM_PRIORITY = 0x1 << 3; + public static final int PERM_READ = 0x1 << 2; + public static final int PERM_WRITE = 0x1 << 1; + public static final int PERM_INHERIT = 0x1 << 0; + + + public static boolean isReadable(final int perm) { + return (perm & PERM_READ) == PERM_READ; + } + + + public static boolean isWriteable(final int perm) { + return (perm & PERM_WRITE) == PERM_WRITE; + } + + + public static boolean isInherited(final int perm) { + return (perm & PERM_INHERIT) == PERM_INHERIT; + } + + + public static String perm2String(final int perm) { + final StringBuffer sb = new StringBuffer("---"); + if (isReadable(perm)) { + sb.replace(0, 1, "R"); + } + + if (isWriteable(perm)) { + sb.replace(1, 2, "W"); + } + + if (isInherited(perm)) { + sb.replace(2, 3, "X"); + } + + return sb.toString(); + } +} diff --git a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/consumer/ConsumeFromWhere.java b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/consumer/ConsumeFromWhere.java new file mode 100644 index 00000000..24c13386 --- /dev/null +++ b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/consumer/ConsumeFromWhere.java @@ -0,0 +1,47 @@ +/** + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.rocketmq.common.consumer; + +/** + * Consumer从哪里开始消费
+ * + * @author shijia.wxr + */ +public enum ConsumeFromWhere { + /** + * 一个新的订阅组第一次启动从队列的最后位置开始消费
+ * 后续再启动接着上次消费的进度开始消费 + */ + CONSUME_FROM_LAST_OFFSET, + + @Deprecated + CONSUME_FROM_LAST_OFFSET_AND_FROM_MIN_WHEN_BOOT_FIRST, + @Deprecated + CONSUME_FROM_MIN_OFFSET, + @Deprecated + CONSUME_FROM_MAX_OFFSET, + /** + * 一个新的订阅组第一次启动从队列的最前位置开始消费
+ * 后续再启动接着上次消费的进度开始消费 + */ + CONSUME_FROM_FIRST_OFFSET, + /** + * 一个新的订阅组第一次启动从指定时间点开始消费
+ * 后续再启动接着上次消费的进度开始消费
+ * 时间点设置参见DefaultMQPushConsumer.consumeTimestamp参数 + */ + CONSUME_FROM_TIMESTAMP, +} diff --git a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/filter/FilterAPI.java b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/filter/FilterAPI.java new file mode 100644 index 00000000..fdd9188b --- /dev/null +++ b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/filter/FilterAPI.java @@ -0,0 +1,55 @@ +/** + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.rocketmq.common.filter; + +import com.alibaba.rocketmq.common.protocol.heartbeat.SubscriptionData; + + +/** + * @author shijia.wxr + * @since 2013-6-15 + */ +public class FilterAPI { + public static SubscriptionData buildSubscriptionData(String topic, String subString) throws Exception { + SubscriptionData subscriptionData = new SubscriptionData(); + subscriptionData.setTopic(topic); + subscriptionData.setSubString(subString); + + if (null == subString || subString.equals(SubscriptionData.SUB_ALL) || subString.length() == 0) { + subscriptionData.setSubString(SubscriptionData.SUB_ALL); + } + else { + String[] tags = subString.split("\\|\\|"); + if (tags != null && tags.length > 0) { + for (String tag : tags) { + if (tag.length() > 0) { + String trimString = tag.trim(); + if (trimString.length() > 0) { + subscriptionData.getTagsSet().add(trimString); + subscriptionData.getCodeSet().add(trimString.hashCode()); + } + } + } + } + else { + throw new Exception("subString split error"); + } + } + + return subscriptionData; + } + +} diff --git a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/filter/Op.java b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/filter/impl/Op.java similarity index 85% rename from rocketmq-common/src/main/java/com/alibaba/rocketmq/common/filter/Op.java rename to rocketmq-common/src/main/java/com/alibaba/rocketmq/common/filter/impl/Op.java index 58676ffe..5bca13f4 100644 --- a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/filter/Op.java +++ b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/filter/impl/Op.java @@ -1,4 +1,4 @@ -package com.alibaba.rocketmq.common.filter; +package com.alibaba.rocketmq.common.filter.impl; /** * @auther lansheng.zj@taobao.com diff --git a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/filter/Operand.java b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/filter/impl/Operand.java similarity index 74% rename from rocketmq-common/src/main/java/com/alibaba/rocketmq/common/filter/Operand.java rename to rocketmq-common/src/main/java/com/alibaba/rocketmq/common/filter/impl/Operand.java index a6d67ac6..5c5a4c4d 100644 --- a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/filter/Operand.java +++ b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/filter/impl/Operand.java @@ -1,4 +1,4 @@ -package com.alibaba.rocketmq.common.filter; +package com.alibaba.rocketmq.common.filter.impl; /** * @auther lansheng.zj@taobao.com diff --git a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/filter/Operator.java b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/filter/impl/Operator.java similarity index 94% rename from rocketmq-common/src/main/java/com/alibaba/rocketmq/common/filter/Operator.java rename to rocketmq-common/src/main/java/com/alibaba/rocketmq/common/filter/impl/Operator.java index 3370ffa8..61555462 100644 --- a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/filter/Operator.java +++ b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/filter/impl/Operator.java @@ -1,4 +1,4 @@ -package com.alibaba.rocketmq.common.filter; +package com.alibaba.rocketmq.common.filter.impl; /** * @auther lansheng.zj@taobao.com @@ -31,7 +31,7 @@ public boolean isCompareable() { } - // -1 С; 0 ; 1 + // -1 小于; 0 等于; 1大于 public int compare(Operator operator) { if (this.priority > operator.priority) return 1; diff --git a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/filter/PolishExpr.java b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/filter/impl/PolishExpr.java similarity index 81% rename from rocketmq-common/src/main/java/com/alibaba/rocketmq/common/filter/PolishExpr.java rename to rocketmq-common/src/main/java/com/alibaba/rocketmq/common/filter/impl/PolishExpr.java index 4c80d9db..0d432f3a 100644 --- a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/filter/PolishExpr.java +++ b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/filter/impl/PolishExpr.java @@ -1,8 +1,8 @@ -package com.alibaba.rocketmq.common.filter; +package com.alibaba.rocketmq.common.filter.impl; -import static com.alibaba.rocketmq.common.filter.Operator.LEFTPARENTHESIS; -import static com.alibaba.rocketmq.common.filter.Operator.RIGHTPARENTHESIS; -import static com.alibaba.rocketmq.common.filter.Operator.createOperator; +import static com.alibaba.rocketmq.common.filter.impl.Operator.LEFTPARENTHESIS; +import static com.alibaba.rocketmq.common.filter.impl.Operator.RIGHTPARENTHESIS; +import static com.alibaba.rocketmq.common.filter.impl.Operator.createOperator; import java.util.ArrayList; import java.util.List; @@ -15,7 +15,7 @@ public class PolishExpr { /** - * ֵ + * 拆分单词 * * @param expression * @return @@ -34,13 +34,13 @@ private static List participle(String expression) { if ((97 <= chValue && chValue <= 122) || (65 <= chValue && chValue <= 90) || (49 <= chValue && chValue <= 57) || 95 == chValue) { - // + // 操作数 if (Type.OPERATOR == preType || Type.SEPAERATOR == preType || Type.NULL == preType || Type.PARENTHESIS == preType) { if (Type.OPERATOR == preType) { - segments - .add(createOperator(expression.substring(wordStartIndex, wordStartIndex + wordLen))); + segments.add(createOperator(expression.substring(wordStartIndex, wordStartIndex + + wordLen))); } wordStartIndex = i; wordLen = 0; @@ -49,10 +49,11 @@ private static List participle(String expression) { wordLen++; } else if (40 == chValue || 41 == chValue) { - // + // 括号 if (Type.OPERATOR == preType) { - segments.add(createOperator(expression.substring(wordStartIndex, wordStartIndex + wordLen))); + segments.add(createOperator(expression + .substring(wordStartIndex, wordStartIndex + wordLen))); wordStartIndex = -1; wordLen = 0; } @@ -66,10 +67,11 @@ else if (Type.OPERAND == preType) { segments.add(createOperator((char) chValue + "")); } else if (38 == chValue || 124 == chValue) { - // + // 操作符 if (Type.OPERAND == preType || Type.SEPAERATOR == preType || Type.PARENTHESIS == preType) { if (Type.OPERAND == preType) { - segments.add(new Operand(expression.substring(wordStartIndex, wordStartIndex + wordLen))); + segments.add(new Operand(expression.substring(wordStartIndex, wordStartIndex + + wordLen))); } wordStartIndex = i; wordLen = 0; @@ -78,10 +80,11 @@ else if (38 == chValue || 124 == chValue) { wordLen++; } else if (32 == chValue || 9 == chValue) { - // ʷָ + // 单词分隔符 if (Type.OPERATOR == preType) { - segments.add(createOperator(expression.substring(wordStartIndex, wordStartIndex + wordLen))); + segments.add(createOperator(expression + .substring(wordStartIndex, wordStartIndex + wordLen))); wordStartIndex = -1; wordLen = 0; } @@ -93,7 +96,7 @@ else if (Type.OPERAND == preType) { preType = Type.SEPAERATOR; } else { - // Ƿַ + // 非法字符 throw new IllegalArgumentException("illegal expression, at index " + i + " " + (char) chValue); } @@ -107,7 +110,7 @@ else if (Type.OPERAND == preType) { /** - * ׺ʽת沨ʽ + * 将中缀表达式转换成逆波兰表达式 * * @param expression * @return @@ -118,7 +121,7 @@ public static List reversePolish(String expression) { /** - * ׺ʽת沨ʽ
+ * 将中缀表达式转换成逆波兰表达式
* Shunting-yard algorithm
* http://en.wikipedia.org/wiki/Shunting_yard_algorithm * @@ -132,15 +135,15 @@ public static List reversePolish(List tokens) { for (int i = 0; i < tokens.size(); i++) { Op token = tokens.get(i); if (isOperand(token)) { - // + // 操作数 segments.add(token); } else if (isLeftParenthesis(token)) { - // + // 左括号 operatorStack.push((Operator) token); } else if (isRightParenthesis(token)) { - // + // 右括号 Operator opNew = null; while (!operatorStack.empty() && LEFTPARENTHESIS != (opNew = operatorStack.pop())) { segments.add(opNew); @@ -149,7 +152,7 @@ else if (isRightParenthesis(token)) { throw new IllegalArgumentException("mismatched parentheses"); } else if (isOperator(token)) { - // ,ݲǽ(,ҽ),ֵ֧IJϵ + // 操作符,暂不考虑结合性(左结合,右结合),支持的操作符都是左结合的 Operator opNew = (Operator) token; if (!operatorStack.empty()) { Operator opOld = operatorStack.peek(); diff --git a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/filter/Type.java b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/filter/impl/Type.java similarity index 73% rename from rocketmq-common/src/main/java/com/alibaba/rocketmq/common/filter/Type.java rename to rocketmq-common/src/main/java/com/alibaba/rocketmq/common/filter/impl/Type.java index 81a2afdc..7c5636b0 100644 --- a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/filter/Type.java +++ b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/filter/impl/Type.java @@ -1,4 +1,4 @@ -package com.alibaba.rocketmq.common.filter; +package com.alibaba.rocketmq.common.filter.impl; /** * @auther lansheng.zj@taobao.com diff --git a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/help/FAQUrl.java b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/help/FAQUrl.java new file mode 100644 index 00000000..004de6dc --- /dev/null +++ b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/help/FAQUrl.java @@ -0,0 +1,105 @@ +/** + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.rocketmq.common.help; + +/** + * 记录一些问题对应的解决方案,减少答疑工作量 + * + * @author shijia.wxr + */ +public class FAQUrl { + // FAQ: Topic不存在如何解决 + public static final String APPLY_TOPIC_URL = // + "https://github.com/alibaba/RocketMQ/issues/55"; + + // FAQ: 同一台机器无法启动多个实例(在多个JVM进程中) + public static final String CLIENT_INSTACNCE_NAME_DUPLICATE_URL = // + "https://github.com/alibaba/RocketMQ/issues/56"; + + // FAQ: Name Server地址不存在 + public static final String NAME_SERVER_ADDR_NOT_EXIST_URL = // + "https://github.com/alibaba/RocketMQ/issues/57"; + + // FAQ: 启动Producer、Consumer失败,Group Name重复 + public static final String GROUP_NAME_DUPLICATE_URL = // + "https://github.com/alibaba/RocketMQ/issues/63"; + + // FAQ: 客户端对象参数校验合法性 + public static final String CLIENT_PARAMETER_CHECK_URL = // + "https://github.com/alibaba/RocketMQ/issues/73"; + + // FAQ: 订阅组不存在如何解决 + public static final String SUBSCRIPTION_GROUP_NOT_EXIST = // + "https://github.com/alibaba/RocketMQ/issues/75"; + + // FAQ: Producer、Consumer服务状态不正确 + public static final String CLIENT_SERVICE_NOT_OK = // + "https://github.com/alibaba/RocketMQ/issues/214"; + + // FAQ: No route info of this topic, TopicABC + public static final String NO_TOPIC_ROUTE_INFO = // + "https://github.com/alibaba/RocketMQ/issues/264"; + + // FAQ: 广播消费者启动加载json文件异常问题 + public static final String LOAD_JSON_EXCEPTION = // + "https://github.com/alibaba/RocketMQ/issues/293"; + + // FAQ: 同一个订阅组内不同Consumer实例订阅关系不同 + public static final String SAME_GROUP_DIFFERENT_TOPIC = // + "https://github.com/alibaba/RocketMQ/issues/332"; + + // FAQ: 主动订阅消息,获取队列列表报Topic不存在 + public static final String MQLIST_NOT_EXIST = // + "https://github.com/alibaba/RocketMQ/issues/336"; + + // + // FAQ: 未收录异常处理办法 + // + public static final String UNEXPECTED_EXCEPTION_URL = // + "https://github.com/alibaba/RocketMQ/issues/64"; + + private static final String TipStringBegin = "\nSee "; + private static final String TipStringEnd = " for further details."; + + + public static String suggestTodo(final String url) { + StringBuilder sb = new StringBuilder(); + sb.append(TipStringBegin); + sb.append(url); + sb.append(TipStringEnd); + return sb.toString(); + } + + + /** + * 对于没有未异常原因指定FAQ的情况,追加默认FAQ + */ + public static String attachDefaultURL(final String errorMessage) { + if (errorMessage != null) { + int index = errorMessage.indexOf(TipStringBegin); + if (-1 == index) { + StringBuilder sb = new StringBuilder(); + sb.append(errorMessage); + sb.append("\n"); + sb.append("For more information, please visit the url, "); + sb.append(UNEXPECTED_EXCEPTION_URL); + return sb.toString(); + } + } + + return errorMessage; + } +} diff --git a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/Message.java b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/message/Message.java similarity index 59% rename from rocketmq-common/src/main/java/com/alibaba/rocketmq/common/Message.java rename to rocketmq-common/src/main/java/com/alibaba/rocketmq/common/message/Message.java index 18ba1a9a..3e535b82 100644 --- a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/Message.java +++ b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/message/Message.java @@ -1,65 +1,52 @@ /** - * $Id: Message.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ -package com.alibaba.rocketmq.common; +package com.alibaba.rocketmq.common.message; -import java.util.Arrays; +import java.io.Serializable; +import java.util.Collection; import java.util.HashMap; import java.util.Map; /** - * ϢProducerConsumerʹ + * 消息,Producer与Consumer使用 * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * @author shijia.wxr + * @since 2013-7-18 */ -public class Message { +public class Message implements Serializable { + private static final long serialVersionUID = 8445773977080406428L; + /** - * Ϣ + * 消息主题 */ private String topic; /** - * Ϣ־ϵͳԤȫӦþʹ + * 消息标志,系统不做干预,完全由应用决定如何使用 */ private int flag; /** - * ϢԣϵͳбԣӦҲԶ + * 消息属性,都是系统属性,禁止应用设置 */ private Map properties; /** - * Ϣ + * 消息体 */ private byte[] body; - /** - * ϢؼʣKeyKEY_SEPARATORѯϢʹã - */ - public static final String PROPERTY_KEYS = "KEYS"; - /** - * ϢǩtagTAG_SEPARATORϢʹã - */ - public static final String PROPERTY_TAGS = "TAGS"; - /** - * ǷȴϢ洢ٷأǵȴˢɻߵȴͬƵ - */ - public static final String PROPERTY_WAIT_STORE_MSG_OK = "WAIT"; - /** - * ϢʱͶʱ伶0ʾʱ0ʾضʱ𣨾弶ڷ˶壩 - */ - public static final String PROPERTY_DELAY_TIME_LEVEL = "DELAY"; - - /** - * ڲʹ - */ - public static final String PROPERTY_REAL_TOPIC = "REAL_TOPIC"; - public static final String PROPERTY_REAL_QUEUE_ID = "REAL_QID"; - public static final String PROPERTY_TRANSACTION_PREPARED = "TRAN_MSG"; - public static final String PROPERTY_PRODUCER_GROUP = "PGROUP"; - - public static final String KEY_SEPARATOR = " "; - - public static final String TAG_SEPARATOR = " "; - public Message() { } @@ -131,27 +118,38 @@ public void setTopic(String topic) { public String getTags() { - return this.getProperty(PROPERTY_TAGS); + return this.getProperty(MessageConst.PROPERTY_TAGS); } public void setTags(String tags) { - this.putProperty(PROPERTY_TAGS, tags); + this.putProperty(MessageConst.PROPERTY_TAGS, tags); } public String getKeys() { - return this.getProperty(PROPERTY_KEYS); + return this.getProperty(MessageConst.PROPERTY_KEYS); } public void setKeys(String keys) { - this.putProperty(PROPERTY_KEYS, keys); + this.putProperty(MessageConst.PROPERTY_KEYS, keys); + } + + + public void setKeys(Collection keys) { + StringBuffer sb = new StringBuffer(); + for (String k : keys) { + sb.append(k); + sb.append(MessageConst.KEY_SEPARATOR); + } + + this.setKeys(sb.toString().trim()); } public int getDelayTimeLevel() { - String t = this.getProperty(PROPERTY_DELAY_TIME_LEVEL); + String t = this.getProperty(MessageConst.PROPERTY_DELAY_TIME_LEVEL); if (t != null) { return Integer.parseInt(t); } @@ -161,12 +159,12 @@ public int getDelayTimeLevel() { public void setDelayTimeLevel(int level) { - this.putProperty(PROPERTY_DELAY_TIME_LEVEL, String.valueOf(level)); + this.putProperty(MessageConst.PROPERTY_DELAY_TIME_LEVEL, String.valueOf(level)); } public boolean isWaitStoreMsgOK() { - String result = this.getProperty(PROPERTY_WAIT_STORE_MSG_OK); + String result = this.getProperty(MessageConst.PROPERTY_WAIT_STORE_MSG_OK); if (null == result) return true; @@ -175,7 +173,7 @@ public boolean isWaitStoreMsgOK() { public void setWaitStoreMsgOK(boolean waitStoreMsgOK) { - this.putProperty(PROPERTY_WAIT_STORE_MSG_OK, Boolean.toString(waitStoreMsgOK)); + this.putProperty(MessageConst.PROPERTY_WAIT_STORE_MSG_OK, Boolean.toString(waitStoreMsgOK)); } @@ -212,6 +210,6 @@ public void setProperties(Map properties) { @Override public String toString() { return "Message [topic=" + topic + ", flag=" + flag + ", properties=" + properties + ", body=" - + Arrays.toString(body) + "]"; + + (body != null ? body.length : 0) + "]"; } } diff --git a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/message/MessageConst.java b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/message/MessageConst.java new file mode 100644 index 00000000..c72de42a --- /dev/null +++ b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/message/MessageConst.java @@ -0,0 +1,48 @@ +/** + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.rocketmq.common.message; + +public class MessageConst { + /** + * 消息关键词,多个Key用KEY_SEPARATOR隔开(查询消息使用) + */ + public static final String PROPERTY_KEYS = "KEYS"; + /** + * 消息标签,只支持设置一个Tag(服务端消息过滤使用) + */ + public static final String PROPERTY_TAGS = "TAGS"; + /** + * 是否等待服务器将消息存储完毕再返回(可能是等待刷盘完成或者等待同步复制到其他服务器) + */ + public static final String PROPERTY_WAIT_STORE_MSG_OK = "WAIT"; + /** + * 消息延时投递时间级别,0表示不延时,大于0表示特定延时级别(具体级别在服务器端定义) + */ + public static final String PROPERTY_DELAY_TIME_LEVEL = "DELAY"; + + /** + * 内部使用 + */ + public static final String PROPERTY_RETRY_TOPIC = "RETRY_TOPIC"; + public static final String PROPERTY_REAL_TOPIC = "REAL_TOPIC"; + public static final String PROPERTY_REAL_QUEUE_ID = "REAL_QID"; + public static final String PROPERTY_TRANSACTION_PREPARED = "TRAN_MSG"; + public static final String PROPERTY_PRODUCER_GROUP = "PGROUP"; + public static final String PROPERTY_MIN_OFFSET = "MIN_OFFSET"; + public static final String PROPERTY_MAX_OFFSET = "MAX_OFFSET"; + + public static final String KEY_SEPARATOR = " "; +} diff --git a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/MessageDecoder.java b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/message/MessageDecoder.java similarity index 79% rename from rocketmq-common/src/main/java/com/alibaba/rocketmq/common/MessageDecoder.java rename to rocketmq-common/src/main/java/com/alibaba/rocketmq/common/message/MessageDecoder.java index 43963070..b39a561a 100644 --- a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/MessageDecoder.java +++ b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/message/MessageDecoder.java @@ -1,279 +1,277 @@ -/** - * $Id: MessageDecoder.java 1831 2013-05-16 01:39:51Z shijia.wxr $ - */ -package com.alibaba.rocketmq.common; - -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.net.SocketAddress; -import java.net.UnknownHostException; -import java.nio.BufferUnderflowException; -import java.nio.ByteBuffer; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.alibaba.rocketmq.common.sysflag.MessageSysFlag; - - -/** - * Ϣ - * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com - */ -public class MessageDecoder { - /** - * ϢID - */ - public final static int MSG_ID_LENGTH = 4 + 8 + 8; - - /** - * 洢¼ֶλ - */ - public final static int MessageMagicCodePostion = 4; - public final static int MessageFlagPostion = 16; - public final static int MessagePhysicOffsetPostion = 28; - public final static int MessageStoreTimestampPostion = 56; - - - public static String createMessageId(final ByteBuffer input, final int time, final ByteBuffer addr, - final long offset) { - input.flip(); - input.limit(MessageDecoder.MSG_ID_LENGTH); - - // Ϣ洢ʱ 4 - input.putInt(time); - // Ϣ洢ַ IP PORT 8 - input.put(addr); - // ϢӦ OFFSET 8 - input.putLong(offset); - - return UtilALl.bytes2string(input.array()); - } - - - public static MessageId decodeMessageId(final String msgId) throws UnknownHostException { - long timestamp; - SocketAddress address; - long offset; - - // ʱ - byte[] data = UtilALl.string2bytes(msgId.substring(0, 8)); - ByteBuffer bb = ByteBuffer.wrap(data); - timestamp = bb.getInt(0) * 1000; - - // ַ - byte[] ip = UtilALl.string2bytes(msgId.substring(8, 16)); - byte[] port = UtilALl.string2bytes(msgId.substring(16, 24)); - bb = ByteBuffer.wrap(port); - int portInt = bb.getInt(0); - address = new InetSocketAddress(InetAddress.getByAddress(ip), portInt); - - // offset - data = UtilALl.string2bytes(msgId.substring(24, 40)); - bb = ByteBuffer.wrap(data); - offset = bb.getLong(0); - - return new MessageId(timestamp, address, offset); - } - - - public static MessageExt decode(java.nio.ByteBuffer byteBuffer) { - return decode(byteBuffer, true); - } - - - /** - * ͻʹãSLAVEҲʹ - */ - public static MessageExt decode(java.nio.ByteBuffer byteBuffer, final boolean readBody) { - try { - MessageExt msgExt = new MessageExt(); - - // 1 TOTALSIZE - int storeSize = byteBuffer.getInt(); - msgExt.setStoreSize(storeSize); - - // 2 MAGICCODE - byteBuffer.getInt(); - - // 3 BODYCRC - int bodyCRC = byteBuffer.getInt(); - msgExt.setBodyCRC(bodyCRC); - - // 4 QUEUEID - int queueId = byteBuffer.getInt(); - msgExt.setQueueId(queueId); - - // 5 FLAG - int flag = byteBuffer.getInt(); - msgExt.setFlag(flag); - - // 6 QUEUEOFFSET - long queueOffset = byteBuffer.getLong(); - msgExt.setQueueOffset(queueOffset); - - // 7 PHYSICALOFFSET - long physicOffset = byteBuffer.getLong(); - msgExt.setCommitLogOffset(physicOffset); - - // 8 SYSFLAG - int sysFlag = byteBuffer.getInt(); - msgExt.setSysFlag(sysFlag); - - // 9 BORNTIMESTAMP - long bornTimeStamp = byteBuffer.getLong(); - msgExt.setBornTimestamp(bornTimeStamp); - - // 10 BORNHOST - byte[] bornHost = new byte[4]; - byteBuffer.get(bornHost, 0, 4); - int port = byteBuffer.getInt(); - msgExt.setBornHost(new InetSocketAddress(InetAddress.getByAddress(bornHost), port)); - - // 11 STORETIMESTAMP - long storeTimestamp = byteBuffer.getLong(); - msgExt.setStoreTimestamp(storeTimestamp); - - // 12 STOREHOST - byte[] storeHost = new byte[4]; - byteBuffer.get(storeHost, 0, 4); - port = byteBuffer.getInt(); - msgExt.setStoreHost(new InetSocketAddress(InetAddress.getByAddress(storeHost), port)); - - // 13 RECONSUMETIMES - int reconsumeTimes = byteBuffer.getInt(); - msgExt.setReconsumeTimes(reconsumeTimes); - - // 14 Prepared Transaction Offset - long preparedTransactionOffset = byteBuffer.getLong(); - msgExt.setPreparedTransactionOffset(preparedTransactionOffset); - - // 15 BODY - int bodyLen = byteBuffer.getInt(); - if (bodyLen > 0) { - if (readBody) { - byte[] body = new byte[bodyLen]; - byteBuffer.get(body); - - // uncompress body - if ((sysFlag & MessageSysFlag.CompressedFlag) == MessageSysFlag.CompressedFlag) { - body = UtilALl.uncompress(body); - } - - msgExt.setBody(body); - } - else { - byteBuffer.position(byteBuffer.position() + bodyLen); - } - } - - // 16 TOPIC - byte topicLen = byteBuffer.get(); - byte[] topic = new byte[(int) topicLen]; - byteBuffer.get(topic); - msgExt.setTopic(new String(topic)); - - // 17 properties - short propertiesLength = byteBuffer.getShort(); - if (propertiesLength > 0) { - byte[] properties = new byte[propertiesLength]; - byteBuffer.get(properties); - String propertiesString = new String(properties); - Map map = string2messageProperties(propertiesString); - msgExt.setProperties(map); - } - - // ϢID - ByteBuffer byteBufferMsgId = ByteBuffer.allocate(MSG_ID_LENGTH); - String msgId = - createMessageId(byteBufferMsgId, (int) (msgExt.getStoreTimestamp() / 1000), - msgExt.getStoreHostBytes(), msgExt.getCommitLogOffset()); - msgExt.setMsgId(msgId); - - return msgExt; - } - catch (UnknownHostException e) { - byteBuffer.position(byteBuffer.limit()); - } - catch (BufferUnderflowException e) { - byteBuffer.position(byteBuffer.limit()); - } - catch (Exception e) { - byteBuffer.position(byteBuffer.limit()); - } - - return null; - } - - - public static List decodes(java.nio.ByteBuffer byteBuffer) { - return decodes(byteBuffer, true); - } - - - /** - * ͻʹ - */ - public static List decodes(java.nio.ByteBuffer byteBuffer, final boolean readBody) { - List msgExts = new ArrayList(); - while (byteBuffer.hasRemaining()) { - MessageExt msgExt = decode(byteBuffer, readBody); - if (null != msgExt) { - msgExts.add(msgExt); - } - else { - log.warn("message decode error."); - break; - } - } - return msgExts; - } - - /** - * лϢ - */ - public static final char NAME_VALUE_SEPARATOR = 1; - public static final char PROPERTY_SEPARATOR = 2; - - - public static String messageProperties2String(Map properties) { - StringBuilder sb = new StringBuilder(); - if (properties != null) { - for (final Map.Entry entry : properties.entrySet()) { - final String name = entry.getKey(); - final String value = entry.getValue(); - - sb.append(name); - sb.append(NAME_VALUE_SEPARATOR); - sb.append(value); - sb.append(PROPERTY_SEPARATOR); - } - } - return sb.toString(); - } - - - public static Map string2messageProperties(final String properties) { - Map map = new HashMap(); - if (properties != null) { - String[] items = properties.split(String.valueOf(PROPERTY_SEPARATOR)); - if (items != null) { - for (String i : items) { - String[] nv = i.split(String.valueOf(NAME_VALUE_SEPARATOR)); - if (nv != null && 2 == nv.length) { - map.put(nv[0], nv[1]); - } - } - } - } - - return map; - } - - private static final Logger log = LoggerFactory.getLogger(MixAll.CommonLoggerName); -} +/** + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.rocketmq.common.message; + +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.SocketAddress; +import java.net.UnknownHostException; +import java.nio.BufferUnderflowException; +import java.nio.ByteBuffer; +import java.nio.charset.Charset; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import com.alibaba.rocketmq.common.UtilAll; +import com.alibaba.rocketmq.common.sysflag.MessageSysFlag; + + +/** + * 消息解码 + * + * @author shijia.wxr + */ +public class MessageDecoder { + /** + * 消息ID定长 + */ + public final static int MSG_ID_LENGTH = 8 + 8; + + /** + * 存储记录各个字段位置 + */ + public final static int MessageMagicCodePostion = 4; + public final static int MessageFlagPostion = 16; + public final static int MessagePhysicOffsetPostion = 28; + public final static int MessageStoreTimestampPostion = 56; + + + public static String createMessageId(final ByteBuffer input, final ByteBuffer addr, final long offset) { + input.flip(); + input.limit(MessageDecoder.MSG_ID_LENGTH); + + // 消息存储主机地址 IP PORT 8 + input.put(addr); + // 消息对应的物理分区 OFFSET 8 + input.putLong(offset); + + return UtilAll.bytes2string(input.array()); + } + + + public static MessageId decodeMessageId(final String msgId) throws UnknownHostException { + SocketAddress address; + long offset; + + // 地址 + byte[] ip = UtilAll.string2bytes(msgId.substring(0, 8)); + byte[] port = UtilAll.string2bytes(msgId.substring(8, 16)); + ByteBuffer bb = ByteBuffer.wrap(port); + int portInt = bb.getInt(0); + address = new InetSocketAddress(InetAddress.getByAddress(ip), portInt); + + // offset + byte[] data = UtilAll.string2bytes(msgId.substring(16, 32)); + bb = ByteBuffer.wrap(data); + offset = bb.getLong(0); + + return new MessageId(address, offset); + } + + + public static MessageExt decode(java.nio.ByteBuffer byteBuffer) { + return decode(byteBuffer, true); + } + + + /** + * 客户端使用,SLAVE也会使用 + */ + public static MessageExt decode(java.nio.ByteBuffer byteBuffer, final boolean readBody) { + try { + MessageExt msgExt = new MessageExt(); + + // 1 TOTALSIZE + int storeSize = byteBuffer.getInt(); + msgExt.setStoreSize(storeSize); + + // 2 MAGICCODE + byteBuffer.getInt(); + + // 3 BODYCRC + int bodyCRC = byteBuffer.getInt(); + msgExt.setBodyCRC(bodyCRC); + + // 4 QUEUEID + int queueId = byteBuffer.getInt(); + msgExt.setQueueId(queueId); + + // 5 FLAG + int flag = byteBuffer.getInt(); + msgExt.setFlag(flag); + + // 6 QUEUEOFFSET + long queueOffset = byteBuffer.getLong(); + msgExt.setQueueOffset(queueOffset); + + // 7 PHYSICALOFFSET + long physicOffset = byteBuffer.getLong(); + msgExt.setCommitLogOffset(physicOffset); + + // 8 SYSFLAG + int sysFlag = byteBuffer.getInt(); + msgExt.setSysFlag(sysFlag); + + // 9 BORNTIMESTAMP + long bornTimeStamp = byteBuffer.getLong(); + msgExt.setBornTimestamp(bornTimeStamp); + + // 10 BORNHOST + byte[] bornHost = new byte[4]; + byteBuffer.get(bornHost, 0, 4); + int port = byteBuffer.getInt(); + msgExt.setBornHost(new InetSocketAddress(InetAddress.getByAddress(bornHost), port)); + + // 11 STORETIMESTAMP + long storeTimestamp = byteBuffer.getLong(); + msgExt.setStoreTimestamp(storeTimestamp); + + // 12 STOREHOST + byte[] storeHost = new byte[4]; + byteBuffer.get(storeHost, 0, 4); + port = byteBuffer.getInt(); + msgExt.setStoreHost(new InetSocketAddress(InetAddress.getByAddress(storeHost), port)); + + // 13 RECONSUMETIMES + int reconsumeTimes = byteBuffer.getInt(); + msgExt.setReconsumeTimes(reconsumeTimes); + + // 14 Prepared Transaction Offset + long preparedTransactionOffset = byteBuffer.getLong(); + msgExt.setPreparedTransactionOffset(preparedTransactionOffset); + + // 15 BODY + int bodyLen = byteBuffer.getInt(); + if (bodyLen > 0) { + if (readBody) { + byte[] body = new byte[bodyLen]; + byteBuffer.get(body); + + // uncompress body + if ((sysFlag & MessageSysFlag.CompressedFlag) == MessageSysFlag.CompressedFlag) { + body = UtilAll.uncompress(body); + } + + msgExt.setBody(body); + } + else { + byteBuffer.position(byteBuffer.position() + bodyLen); + } + } + + // 16 TOPIC + byte topicLen = byteBuffer.get(); + byte[] topic = new byte[(int) topicLen]; + byteBuffer.get(topic); + msgExt.setTopic(new String(topic)); + + // 17 properties + short propertiesLength = byteBuffer.getShort(); + if (propertiesLength > 0) { + byte[] properties = new byte[propertiesLength]; + byteBuffer.get(properties); + String propertiesString = new String(properties, Charset.forName("UTF-8")); + Map map = string2messageProperties(propertiesString); + msgExt.setProperties(map); + } + + // 消息ID + ByteBuffer byteBufferMsgId = ByteBuffer.allocate(MSG_ID_LENGTH); + String msgId = + createMessageId(byteBufferMsgId, msgExt.getStoreHostBytes(), msgExt.getCommitLogOffset()); + msgExt.setMsgId(msgId); + + return msgExt; + } + catch (UnknownHostException e) { + byteBuffer.position(byteBuffer.limit()); + } + catch (BufferUnderflowException e) { + byteBuffer.position(byteBuffer.limit()); + } + catch (Exception e) { + byteBuffer.position(byteBuffer.limit()); + } + + return null; + } + + + public static List decodes(java.nio.ByteBuffer byteBuffer) { + return decodes(byteBuffer, true); + } + + + /** + * 客户端使用 + */ + public static List decodes(java.nio.ByteBuffer byteBuffer, final boolean readBody) { + List msgExts = new ArrayList(); + while (byteBuffer.hasRemaining()) { + MessageExt msgExt = decode(byteBuffer, readBody); + if (null != msgExt) { + msgExts.add(msgExt); + } + else { + break; + } + } + return msgExts; + } + + /** + * 序列化消息属性 + */ + public static final char NAME_VALUE_SEPARATOR = 1; + public static final char PROPERTY_SEPARATOR = 2; + + + public static String messageProperties2String(Map properties) { + StringBuilder sb = new StringBuilder(); + if (properties != null) { + for (final Map.Entry entry : properties.entrySet()) { + final String name = entry.getKey(); + final String value = entry.getValue(); + + sb.append(name); + sb.append(NAME_VALUE_SEPARATOR); + sb.append(value); + sb.append(PROPERTY_SEPARATOR); + } + } + return sb.toString(); + } + + + public static Map string2messageProperties(final String properties) { + Map map = new HashMap(); + if (properties != null) { + String[] items = properties.split(String.valueOf(PROPERTY_SEPARATOR)); + if (items != null) { + for (String i : items) { + String[] nv = i.split(String.valueOf(NAME_VALUE_SEPARATOR)); + if (nv != null && 2 == nv.length) { + map.put(nv[0], nv[1]); + } + } + } + } + + return map; + } +} diff --git a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/MessageExt.java b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/message/MessageExt.java similarity index 71% rename from rocketmq-common/src/main/java/com/alibaba/rocketmq/common/MessageExt.java rename to rocketmq-common/src/main/java/com/alibaba/rocketmq/common/message/MessageExt.java index a03e4cfd..8185a07f 100644 --- a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/MessageExt.java +++ b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/message/MessageExt.java @@ -1,44 +1,60 @@ /** - * $Id: MessageExt.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ -package com.alibaba.rocketmq.common; +package com.alibaba.rocketmq.common.message; import java.net.InetSocketAddress; import java.net.SocketAddress; import java.nio.ByteBuffer; +import com.alibaba.rocketmq.common.TopicFilterType; import com.alibaba.rocketmq.common.sysflag.MessageSysFlag; /** - * Ϣչԣڷϲ˶ + * 消息扩展属性,在服务器上产生此对象 * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * @author shijia.wxr + * @since 2013-7-18 */ public class MessageExt extends Message { - // ID + private static final long serialVersionUID = 5720810158625748049L; + + // 队列ID private int queueId; - // 洢¼С + // 存储记录大小 private int storeSize; - // ƫ + // 队列偏移量 private long queueOffset; - // Ϣ־λ + // 消息标志位 private int sysFlag; - // Ϣڿͻ˴ʱ + // 消息在客户端创建时间戳 private long bornTimestamp; - // Ϣ + // 消息来自哪里 private SocketAddress bornHost; - // Ϣڷ洢ʱ + // 消息在服务器存储时间戳 private long storeTimestamp; - // Ϣ洢ĸ + // 消息存储在哪个服务器 private SocketAddress storeHost; - // ϢID + // 消息ID private String msgId; - // ϢӦCommit Log Offset + // 消息对应的Commit Log Offset private long commitLogOffset; - // ϢCRC + // 消息体CRC private int bodyCRC; - // ǰϢij˼Σ֮ + // 当前消息被某个订阅组重新消费了几次(订阅组之间独立计数) private int reconsumeTimes; private long preparedTransactionOffset; @@ -60,7 +76,7 @@ public MessageExt(int queueId, long bornTimestamp, SocketAddress bornHost, long /** - * SocketAddress ----> ByteBuffer ת8ֽ + * SocketAddress ----> ByteBuffer 转化成8个字节 */ public static ByteBuffer SocketAddress2ByteBuffer(SocketAddress socketAddress) { ByteBuffer byteBuffer = ByteBuffer.allocate(8); @@ -73,7 +89,7 @@ public static ByteBuffer SocketAddress2ByteBuffer(SocketAddress socketAddress) { /** - * ȡbornHostֽʽ8ֽ HOST + PORT + * 获取bornHost字节形式,8个字节 HOST + PORT */ public ByteBuffer getBornHostBytes() { return SocketAddress2ByteBuffer(this.bornHost); @@ -81,7 +97,7 @@ public ByteBuffer getBornHostBytes() { /** - * ȡstorehostֽʽ8ֽ HOST + PORT + * 获取storehost字节形式,8个字节 HOST + PORT */ public ByteBuffer getStoreHostBytes() { return SocketAddress2ByteBuffer(this.storeHost); @@ -123,6 +139,16 @@ public String getBornHostString() { } + public String getBornHostNameString() { + if (this.bornHost != null) { + InetSocketAddress inetSocketAddress = (InetSocketAddress) this.bornHost; + return inetSocketAddress.getAddress().getHostName(); + } + + return null; + } + + public void setBornHost(SocketAddress bornHost) { this.bornHost = bornHost; } @@ -227,16 +253,6 @@ public void setReconsumeTimes(int reconsumeTimes) { } - @Override - public String toString() { - return "MessageExt [queueId=" + queueId + ", storeSize=" + storeSize + ", queueOffset=" + queueOffset - + ", sysFlag=" + sysFlag + ", bornTimestamp=" + bornTimestamp + ", bornHost=" + bornHost - + ", storeTimestamp=" + storeTimestamp + ", storeHost=" + storeHost + ", msgId=" + msgId - + ", physicOffset=" + commitLogOffset + ", bodyCRC=" + bodyCRC + ", reconsumeTimes=" + reconsumeTimes - + ", toString()=" + super.toString() + "]"; - } - - public long getPreparedTransactionOffset() { return preparedTransactionOffset; } @@ -245,4 +261,15 @@ public long getPreparedTransactionOffset() { public void setPreparedTransactionOffset(long preparedTransactionOffset) { this.preparedTransactionOffset = preparedTransactionOffset; } + + + @Override + public String toString() { + return "MessageExt [queueId=" + queueId + ", storeSize=" + storeSize + ", queueOffset=" + queueOffset + + ", sysFlag=" + sysFlag + ", bornTimestamp=" + bornTimestamp + ", bornHost=" + bornHost + + ", storeTimestamp=" + storeTimestamp + ", storeHost=" + storeHost + ", msgId=" + msgId + + ", commitLogOffset=" + commitLogOffset + ", bodyCRC=" + bodyCRC + ", reconsumeTimes=" + + reconsumeTimes + ", preparedTransactionOffset=" + preparedTransactionOffset + + ", toString()=" + super.toString() + "]"; + } } diff --git a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/message/MessageId.java b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/message/MessageId.java new file mode 100644 index 00000000..00ff09a0 --- /dev/null +++ b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/message/MessageId.java @@ -0,0 +1,53 @@ +/** + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.rocketmq.common.message; + +import java.net.SocketAddress; + + +/** + * @author shijia.wxr + */ +public class MessageId { + private SocketAddress address; + private long offset; + + + public MessageId(SocketAddress address, long offset) { + this.address = address; + this.offset = offset; + } + + + public SocketAddress getAddress() { + return address; + } + + + public void setAddress(SocketAddress address) { + this.address = address; + } + + + public long getOffset() { + return offset; + } + + + public void setOffset(long offset) { + this.offset = offset; + } +} diff --git a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/MessageQueue.java b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/message/MessageQueue.java similarity index 58% rename from rocketmq-common/src/main/java/com/alibaba/rocketmq/common/MessageQueue.java rename to rocketmq-common/src/main/java/com/alibaba/rocketmq/common/message/MessageQueue.java index a43c0abb..c999fb92 100644 --- a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/MessageQueue.java +++ b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/message/MessageQueue.java @@ -1,19 +1,40 @@ /** - * $Id: MessageQueue.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ -package com.alibaba.rocketmq.common; +package com.alibaba.rocketmq.common.message; + +import java.io.Serializable; + /** - * Ϣݽṹṩ + * 消息队列数据结构,对外提供 * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * @author shijia.wxr */ -public class MessageQueue { +public class MessageQueue implements Comparable, Serializable { + private static final long serialVersionUID = 6191200464116433425L; private String topic; private String brokerName; private int queueId; + public MessageQueue() { + + } + + public MessageQueue(String topic, String brokerName, int queueId) { this.topic = topic; this.brokerName = brokerName; @@ -51,12 +72,6 @@ public void setQueueId(int queueId) { } - @Override - public String toString() { - return "MessageQueue [topic=" + topic + ", brokerName=" + brokerName + ", queueId=" + queueId + "]"; - } - - @Override public int hashCode() { final int prime = 31; @@ -93,4 +108,30 @@ else if (!topic.equals(other.topic)) return false; return true; } + + + @Override + public String toString() { + return "MessageQueue [topic=" + topic + ", brokerName=" + brokerName + ", queueId=" + queueId + "]"; + } + + + @Override + public int compareTo(MessageQueue o) { + { + int result = this.topic.compareTo(o.topic); + if (result != 0) { + return result; + } + } + + { + int result = this.brokerName.compareTo(o.brokerName); + if (result != 0) { + return result; + } + } + + return this.queueId - o.queueId; + } } diff --git a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/namesrv/NamesrvConfig.java b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/namesrv/NamesrvConfig.java index 866f49c5..42725843 100644 --- a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/namesrv/NamesrvConfig.java +++ b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/namesrv/NamesrvConfig.java @@ -3,98 +3,23 @@ */ package com.alibaba.rocketmq.common.namesrv; -import java.beans.PropertyChangeListener; -import java.beans.PropertyChangeSupport; import java.io.File; import com.alibaba.rocketmq.common.MixAll; /** - * Name server + * Name server 的配置类 * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * @author shijia.wxr * @author lansheng.zj@taobao.com - * */ public class NamesrvConfig { - private String rocketmqHome = System.getenv(MixAll.ROCKETMQ_HOME_ENV); - private String orderConfPath = System.getProperty("user.home") + File.separator + "namesrv" + File.separator - + "orderConf.properties"; - private String brokerAddrConfPath = System.getProperty("user.home") + File.separator + "namesrv" - + File.separator + "brokerAddr.properties"; - - // namesrv Ⱥַ - private String namesrvAddr; - // ͬnamesrvϢijʱʱ - private long syncTimeout = 3000L; - // ͬnamesrvϢʱ - private long syncInterval = 30 * 1000L; - // һspreadȴʱ - private long groupWaitTimeout = 4000L; - // brokerȡϢʱʱ - private long pullFormBrokerTimeout = 3000L; - // brokerȡϢʱ - private long pullFormBrokerInterval = 30 * 1000L; - // web serverϻȡnamesrvַбʱ - private long addressInterval = 5 * 60 * 1000L; - - private final PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(this); - - - public void addPropertyChangeListener(final String propertyName, final PropertyChangeListener listener) { - this.propertyChangeSupport.addPropertyChangeListener(propertyName, listener); - } - - - public long getPullFormBrokerInterval() { - return pullFormBrokerInterval; - } - - - public void setPullFormBrokerInterval(long pullFormBrokerInterval) { - this.pullFormBrokerInterval = pullFormBrokerInterval; - } - - - public long getAddressInterval() { - return addressInterval; - } - - - public void setAddressInterval(long addressInterval) { - this.addressInterval = addressInterval; - } - - - public void removePropertyChangeListener(final PropertyChangeListener listener) { - this.propertyChangeSupport.removePropertyChangeListener(listener); - } - - - public void firePropertyChange(String propertyName, Object oldValue, Object newValue) { - propertyChangeSupport.firePropertyChange(propertyName, oldValue, newValue); - } - - - public long getSyncInterval() { - return syncInterval; - } - - - public void setSyncInterval(long syncInterval) { - this.syncInterval = syncInterval; - } - - - public long getSyncTimeout() { - return syncTimeout; - } - - - public void setSyncTimeout(long syncTimeout) { - this.syncTimeout = syncTimeout; - } + private String rocketmqHome = System.getProperty(MixAll.ROCKETMQ_HOME_PROPERTY, + System.getenv(MixAll.ROCKETMQ_HOME_ENV)); + // 通用的KV配置持久化地址 + private String kvConfigPath = System.getProperty("user.home") + File.separator + "namesrv" + + File.separator + "kvConfig.json"; public String getRocketmqHome() { @@ -107,53 +32,12 @@ public void setRocketmqHome(String rocketmqHome) { } - public String getNamesrvAddr() { - return namesrvAddr; - } - - - public void setNamesrvAddr(String namesrvAddr) { - this.namesrvAddr = namesrvAddr; - } - - - public long getGroupWaitTimeout() { - return groupWaitTimeout; - } - - - public void setGroupWaitTimeout(long groupWaitTimeout) { - this.groupWaitTimeout = groupWaitTimeout; - } - - - public long getPullFormBrokerTimeout() { - return pullFormBrokerTimeout; - } - - - public void setPullFormBrokerTimeout(long pullFormBrokerTimeout) { - this.pullFormBrokerTimeout = pullFormBrokerTimeout; - } - - - public String getOrderConfPath() { - return orderConfPath; + public String getKvConfigPath() { + return kvConfigPath; } - public void setOrderConfPath(String orderConfPath) { - this.orderConfPath = orderConfPath; + public void setKvConfigPath(String kvConfigPath) { + this.kvConfigPath = kvConfigPath; } - - - public String getBrokerAddrConfPath() { - return brokerAddrConfPath; - } - - - public void setBrokerAddrConfPath(String brokerAddrConfPath) { - this.brokerAddrConfPath = brokerAddrConfPath; - } - } diff --git a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/namesrv/NamesrvUtil.java b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/namesrv/NamesrvUtil.java new file mode 100644 index 00000000..84f696c9 --- /dev/null +++ b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/namesrv/NamesrvUtil.java @@ -0,0 +1,10 @@ +package com.alibaba.rocketmq.common.namesrv; + +/** + * @author shijia.wxr + * @since 2013-7-5 + */ +public class NamesrvUtil { + public static final String NAMESPACE_ORDER_TOPIC_CONFIG = "ORDER_TOPIC_CONFIG"; + public static final String NAMESPACE_PROJECT_CONFIG = "PROJECT_CONFIG"; +} diff --git a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/namesrv/RegisterBrokerResult.java b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/namesrv/RegisterBrokerResult.java new file mode 100644 index 00000000..9a219262 --- /dev/null +++ b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/namesrv/RegisterBrokerResult.java @@ -0,0 +1,30 @@ +package com.alibaba.rocketmq.common.namesrv; + +/** + * @author shijia.wxr + * @since 2013-7-8 + */ +public class RegisterBrokerResult { + private String haServerAddr; + private String masterAddr; + + + public String getHaServerAddr() { + return haServerAddr; + } + + + public void setHaServerAddr(String haServerAddr) { + this.haServerAddr = haServerAddr; + } + + + public String getMasterAddr() { + return masterAddr; + } + + + public void setMasterAddr(String masterAddr) { + this.masterAddr = masterAddr; + } +} diff --git a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/namesrv/TopAddressing.java b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/namesrv/TopAddressing.java index d2e0b155..d153885b 100644 --- a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/namesrv/TopAddressing.java +++ b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/namesrv/TopAddressing.java @@ -14,16 +14,17 @@ import org.slf4j.LoggerFactory; import com.alibaba.rocketmq.common.MixAll; +import com.alibaba.rocketmq.common.constant.LoggerName; +import com.alibaba.rocketmq.common.help.FAQUrl; /** - * Ѱַ - * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * 寻址服务 * + * @author shijia.wxr */ public class TopAddressing { - private static final Logger log = LoggerFactory.getLogger(MixAll.CommonLoggerName); + private static final Logger log = LoggerFactory.getLogger(LoggerName.CommonLoggerName); private HttpClient httpClient = new HttpClient(); private String nsAddr; @@ -86,6 +87,8 @@ public final String fetchNSAddr() { String errorMsg = "connect to " + MixAll.WS_ADDR + " failed, maybe the domain name " + MixAll.WS_DOMAIN_NAME + " not bind in /etc/hosts"; + errorMsg += FAQUrl.suggestTodo(FAQUrl.NAME_SERVER_ADDR_NOT_EXIST_URL); + log.warn(errorMsg); System.out.println(errorMsg); return null; diff --git a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/namesrv/TopicRuntimeData.java b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/namesrv/TopicRuntimeData.java deleted file mode 100644 index e37320bf..00000000 --- a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/namesrv/TopicRuntimeData.java +++ /dev/null @@ -1,193 +0,0 @@ -package com.alibaba.rocketmq.common.namesrv; - -import static com.alibaba.rocketmq.common.protocol.route.ObjectConverter.topicRuntimeData2TopicRuntimeInfo; -import static com.alibaba.rocketmq.common.protocol.route.ObjectConverter.topicRuntimeInfo2TopicRuntimeData; - -import java.beans.PropertyChangeListener; -import java.beans.PropertyChangeSupport; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; - -import com.google.protobuf.InvalidProtocolBufferException; -import com.alibaba.rocketmq.common.protocol.route.ObjectConverter; -import com.alibaba.rocketmq.common.protocol.MQProtos.TopicRuntimeInfo; -import com.alibaba.rocketmq.common.protocol.route.BrokerData; -import com.alibaba.rocketmq.common.protocol.route.QueueData; - - -/** - * ʱռbrokertopicصϢ,ֻлnameserver˳־ûϢ - * - * @author lansheng.zj@taobao.com - */ -public class TopicRuntimeData { - - public static final String ORDER_PREFIX = "topic.num."; - - private transient Map> topicBrokers; - private Map topicOrderConfs; - private transient Map brokers; - private List brokerList; - - private final PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(this); - - - // FIXME cluster information - // private Map clusterInfo; - - public TopicRuntimeData() { - topicBrokers = new HashMap>(); - topicOrderConfs = new HashMap(); - brokers = new HashMap(); - brokerList = new ArrayList(); - } - - - public byte[] encode() { - return topicRuntimeData2TopicRuntimeInfo(this).toByteArray(); - } - - - public byte[] encodeSpecific() { - TopicRuntimeData serial = new TopicRuntimeData(); - serial.setTopicOrderConfs(topicOrderConfs); - serial.setBrokerList(brokerList); - return topicRuntimeData2TopicRuntimeInfo(serial).toByteArray(); - } - - - public static TopicRuntimeData decode(byte[] data) throws InvalidProtocolBufferException { - TopicRuntimeInfo topicRuntimeInfo = TopicRuntimeInfo.parseFrom(data); - return topicRuntimeInfo2TopicRuntimeData(topicRuntimeInfo); - } - - - public String encodeOrderTopicAsString() { - StringBuilder encode = new StringBuilder(); - boolean isFirst = true; - for (Entry entry : topicOrderConfs.entrySet()) { - if (!isFirst) - encode.append("\n"); - - encode.append(entry.getKey() + "=" + entry.getValue()); - isFirst = false; - } - - return encode.toString(); - } - - - public String encodeBrokerListAsString() { - StringBuilder encode = new StringBuilder(); - boolean isFirst = true; - for (String address : brokerList) { - if (!isFirst) - encode.append(";"); - - encode.append(address); - isFirst = false; - } - - return encode.toString(); - } - - - public String getOrderConfByTopic(String topic) { - String conf = topicOrderConfs.get(ORDER_PREFIX + topic); - if (null != conf && !"".equals(conf)) { - return ORDER_PREFIX + topic + "=" + conf; - } - return ""; - } - - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((topicBrokers == null) ? 0 : topicBrokers.hashCode()); - result = prime * result + ((topicOrderConfs == null) ? 0 : topicOrderConfs.hashCode()); - result = prime * result + ((brokers == null) ? 0 : brokers.hashCode()); - result = prime * result + ((brokerList == null) ? 0 : brokerList.hashCode()); - return result; - } - - - @Override - public boolean equals(Object obj) { - - // TODO ԱȽϵܿ - - if (this == obj) - return true; - if (!(obj instanceof TopicRuntimeData)) - return false; - - TopicRuntimeData newTrd = (TopicRuntimeData) obj; - boolean equal = - ObjectConverter.equals(getTopicBrokers(), newTrd.getTopicBrokers()) - && ObjectConverter.equals(getTopicOrderConfs(), newTrd.getTopicOrderConfs()) - && ObjectConverter.equals(getBrokers(), newTrd.getBrokers()) - && ObjectConverter.equals(getBrokerList(), newTrd.getBrokerList()); - - return equal; - } - - - public void addPropertyChangeListener(final String propertyName, final PropertyChangeListener listener) { - propertyChangeSupport.addPropertyChangeListener(propertyName, listener); - } - - - public void removePropertyChangeListener(final PropertyChangeListener listener) { - propertyChangeSupport.removePropertyChangeListener(listener); - } - - - public void firePropertyChange(String propertyName, Object oldValue, Object newValue) { - propertyChangeSupport.firePropertyChange(propertyName, oldValue, newValue); - } - - - public Map> getTopicBrokers() { - return topicBrokers; - } - - - public void setTopicBrokers(Map> topicBrokers) { - this.topicBrokers = topicBrokers; - } - - - public Map getTopicOrderConfs() { - return topicOrderConfs; - } - - - public void setTopicOrderConfs(Map topicOrderConfs) { - this.topicOrderConfs = topicOrderConfs; - } - - - public Map getBrokers() { - return brokers; - } - - - public void setBrokers(Map brokers) { - this.brokers = brokers; - } - - - public List getBrokerList() { - return brokerList; - } - - - public void setBrokerList(List brokerList) { - this.brokerList = brokerList; - } -} diff --git a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/MQProtos.java b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/MQProtos.java index 9c71a9c7..1d6a9998 100644 --- a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/MQProtos.java +++ b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/MQProtos.java @@ -4,8449 +4,562 @@ package com.alibaba.rocketmq.common.protocol; public final class MQProtos { - private MQProtos() {} - public static void registerAllExtensions( - com.google.protobuf.ExtensionRegistry registry) { - } - public enum MQRequestCode - implements com.google.protobuf.ProtocolMessageEnum { - SEND_MESSAGE(0, 10), - PULL_MESSAGE(1, 11), - QUERY_MESSAGE(2, 12), - QUERY_BROKER_OFFSET(3, 13), - QUERY_CONSUMER_OFFSET(4, 14), - UPDATE_CONSUMER_OFFSET(5, 15), - UPDATE_AND_CREATE_TOPIC(6, 17), - DELETE_TOPIC(7, 19), - GET_ALL_TOPIC_CONFIG(8, 21), - GET_TOPIC_CONFIG_LIST(9, 22), - GET_TOPIC_NAME_LIST(10, 23), - PULL_ALL_CONSUMER_OFFSET(11, 24), - UPDATE_BROKER_CONFIG(12, 25), - GET_BROKER_CONFIG(13, 26), - TRIGGER_DELETE_FILES(14, 27), - GET_BROKER_RUNTIME_INFO(15, 28), - SEARCH_OFFSET_BY_TIMESTAMP(16, 29), - GET_MAX_OFFSET(17, 30), - GET_MIN_OFFSET(18, 31), - GET_EARLIEST_MSG_STORETIME(19, 32), - VIEW_MESSAGE_BY_ID(20, 33), - HEART_BEAT(21, 34), - UNREGISTER_CLIENT(22, 35), - CONSUMER_SEND_MSG_BACK(23, 36), - END_TRANSACTION(24, 37), - CHECK_TRANSACTION_STATE(25, 38), - REGISTER_BROKER(26, 100), - UNREGISTER_BROKER(27, 101), - GET_BROKER_LIST(28, 102), - REGISTER_ORDER_TOPIC(29, 103), - UNREGISTER_ORDER_TOPIC(30, 104), - GET_ORDER_TOPIC_LIST(31, 105), - UPDATE_NAMESRV_CONFIG(32, 106), - GET_NAMESRV_CONFIG(33, 107), - GET_NAMESRV_RUNTIME_INFO(34, 108), - GET_ROUTEINTO_BY_TOPIC(35, 109), - SYNC_NAMESRV_RUNTIME_CONF(36, 110), - REGISTER_BROKER_SINGLE(37, 111), - UNREGISTER_BROKER_SINGLE(38, 112), - REGISTER_ORDER_TOPIC_SINGLE(39, 113), - UNREGISTER_ORDER_TOPIC_SINGLE(40, 114), - ; - - public static final int SEND_MESSAGE_VALUE = 10; - public static final int PULL_MESSAGE_VALUE = 11; - public static final int QUERY_MESSAGE_VALUE = 12; - public static final int QUERY_BROKER_OFFSET_VALUE = 13; - public static final int QUERY_CONSUMER_OFFSET_VALUE = 14; - public static final int UPDATE_CONSUMER_OFFSET_VALUE = 15; - public static final int UPDATE_AND_CREATE_TOPIC_VALUE = 17; - public static final int DELETE_TOPIC_VALUE = 19; - public static final int GET_ALL_TOPIC_CONFIG_VALUE = 21; - public static final int GET_TOPIC_CONFIG_LIST_VALUE = 22; - public static final int GET_TOPIC_NAME_LIST_VALUE = 23; - public static final int PULL_ALL_CONSUMER_OFFSET_VALUE = 24; - public static final int UPDATE_BROKER_CONFIG_VALUE = 25; - public static final int GET_BROKER_CONFIG_VALUE = 26; - public static final int TRIGGER_DELETE_FILES_VALUE = 27; - public static final int GET_BROKER_RUNTIME_INFO_VALUE = 28; - public static final int SEARCH_OFFSET_BY_TIMESTAMP_VALUE = 29; - public static final int GET_MAX_OFFSET_VALUE = 30; - public static final int GET_MIN_OFFSET_VALUE = 31; - public static final int GET_EARLIEST_MSG_STORETIME_VALUE = 32; - public static final int VIEW_MESSAGE_BY_ID_VALUE = 33; - public static final int HEART_BEAT_VALUE = 34; - public static final int UNREGISTER_CLIENT_VALUE = 35; - public static final int CONSUMER_SEND_MSG_BACK_VALUE = 36; - public static final int END_TRANSACTION_VALUE = 37; - public static final int CHECK_TRANSACTION_STATE_VALUE = 38; - public static final int REGISTER_BROKER_VALUE = 100; - public static final int UNREGISTER_BROKER_VALUE = 101; - public static final int GET_BROKER_LIST_VALUE = 102; - public static final int REGISTER_ORDER_TOPIC_VALUE = 103; - public static final int UNREGISTER_ORDER_TOPIC_VALUE = 104; - public static final int GET_ORDER_TOPIC_LIST_VALUE = 105; - public static final int UPDATE_NAMESRV_CONFIG_VALUE = 106; - public static final int GET_NAMESRV_CONFIG_VALUE = 107; - public static final int GET_NAMESRV_RUNTIME_INFO_VALUE = 108; - public static final int GET_ROUTEINTO_BY_TOPIC_VALUE = 109; - public static final int SYNC_NAMESRV_RUNTIME_CONF_VALUE = 110; - public static final int REGISTER_BROKER_SINGLE_VALUE = 111; - public static final int UNREGISTER_BROKER_SINGLE_VALUE = 112; - public static final int REGISTER_ORDER_TOPIC_SINGLE_VALUE = 113; - public static final int UNREGISTER_ORDER_TOPIC_SINGLE_VALUE = 114; - - - public final int getNumber() { return value; } - - public static MQRequestCode valueOf(int value) { - switch (value) { - case 10: return SEND_MESSAGE; - case 11: return PULL_MESSAGE; - case 12: return QUERY_MESSAGE; - case 13: return QUERY_BROKER_OFFSET; - case 14: return QUERY_CONSUMER_OFFSET; - case 15: return UPDATE_CONSUMER_OFFSET; - case 17: return UPDATE_AND_CREATE_TOPIC; - case 19: return DELETE_TOPIC; - case 21: return GET_ALL_TOPIC_CONFIG; - case 22: return GET_TOPIC_CONFIG_LIST; - case 23: return GET_TOPIC_NAME_LIST; - case 24: return PULL_ALL_CONSUMER_OFFSET; - case 25: return UPDATE_BROKER_CONFIG; - case 26: return GET_BROKER_CONFIG; - case 27: return TRIGGER_DELETE_FILES; - case 28: return GET_BROKER_RUNTIME_INFO; - case 29: return SEARCH_OFFSET_BY_TIMESTAMP; - case 30: return GET_MAX_OFFSET; - case 31: return GET_MIN_OFFSET; - case 32: return GET_EARLIEST_MSG_STORETIME; - case 33: return VIEW_MESSAGE_BY_ID; - case 34: return HEART_BEAT; - case 35: return UNREGISTER_CLIENT; - case 36: return CONSUMER_SEND_MSG_BACK; - case 37: return END_TRANSACTION; - case 38: return CHECK_TRANSACTION_STATE; - case 100: return REGISTER_BROKER; - case 101: return UNREGISTER_BROKER; - case 102: return GET_BROKER_LIST; - case 103: return REGISTER_ORDER_TOPIC; - case 104: return UNREGISTER_ORDER_TOPIC; - case 105: return GET_ORDER_TOPIC_LIST; - case 106: return UPDATE_NAMESRV_CONFIG; - case 107: return GET_NAMESRV_CONFIG; - case 108: return GET_NAMESRV_RUNTIME_INFO; - case 109: return GET_ROUTEINTO_BY_TOPIC; - case 110: return SYNC_NAMESRV_RUNTIME_CONF; - case 111: return REGISTER_BROKER_SINGLE; - case 112: return UNREGISTER_BROKER_SINGLE; - case 113: return REGISTER_ORDER_TOPIC_SINGLE; - case 114: return UNREGISTER_ORDER_TOPIC_SINGLE; - default: return null; - } + private MQProtos() { } - - public static com.google.protobuf.Internal.EnumLiteMap - internalGetValueMap() { - return internalValueMap; - } - private static com.google.protobuf.Internal.EnumLiteMap - internalValueMap = - new com.google.protobuf.Internal.EnumLiteMap() { - public MQRequestCode findValueByNumber(int number) { - return MQRequestCode.valueOf(number); - } - }; - - public final com.google.protobuf.Descriptors.EnumValueDescriptor - getValueDescriptor() { - return getDescriptor().getValues().get(index); - } - public final com.google.protobuf.Descriptors.EnumDescriptor - getDescriptorForType() { - return getDescriptor(); - } - public static final com.google.protobuf.Descriptors.EnumDescriptor - getDescriptor() { - return com.alibaba.rocketmq.common.protocol.MQProtos.getDescriptor().getEnumTypes().get(0); - } - - private static final MQRequestCode[] VALUES = { - SEND_MESSAGE, PULL_MESSAGE, QUERY_MESSAGE, QUERY_BROKER_OFFSET, QUERY_CONSUMER_OFFSET, UPDATE_CONSUMER_OFFSET, UPDATE_AND_CREATE_TOPIC, DELETE_TOPIC, GET_ALL_TOPIC_CONFIG, GET_TOPIC_CONFIG_LIST, GET_TOPIC_NAME_LIST, PULL_ALL_CONSUMER_OFFSET, UPDATE_BROKER_CONFIG, GET_BROKER_CONFIG, TRIGGER_DELETE_FILES, GET_BROKER_RUNTIME_INFO, SEARCH_OFFSET_BY_TIMESTAMP, GET_MAX_OFFSET, GET_MIN_OFFSET, GET_EARLIEST_MSG_STORETIME, VIEW_MESSAGE_BY_ID, HEART_BEAT, UNREGISTER_CLIENT, CONSUMER_SEND_MSG_BACK, END_TRANSACTION, CHECK_TRANSACTION_STATE, REGISTER_BROKER, UNREGISTER_BROKER, GET_BROKER_LIST, REGISTER_ORDER_TOPIC, UNREGISTER_ORDER_TOPIC, GET_ORDER_TOPIC_LIST, UPDATE_NAMESRV_CONFIG, GET_NAMESRV_CONFIG, GET_NAMESRV_RUNTIME_INFO, GET_ROUTEINTO_BY_TOPIC, SYNC_NAMESRV_RUNTIME_CONF, REGISTER_BROKER_SINGLE, UNREGISTER_BROKER_SINGLE, REGISTER_ORDER_TOPIC_SINGLE, UNREGISTER_ORDER_TOPIC_SINGLE, - }; - - public static MQRequestCode valueOf( - com.google.protobuf.Descriptors.EnumValueDescriptor desc) { - if (desc.getType() != getDescriptor()) { - throw new java.lang.IllegalArgumentException( - "EnumValueDescriptor is not for this type."); - } - return VALUES[desc.getIndex()]; - } - - private final int index; - private final int value; - - private MQRequestCode(int index, int value) { - this.index = index; - this.value = value; - } - - // @@protoc_insertion_point(enum_scope:rocketmq.MQRequestCode) - } - - public enum MQResponseCode - implements com.google.protobuf.ProtocolMessageEnum { - FLUSH_DISK_TIMEOUT(0, 10), - SLAVE_NOT_AVAILABLE(1, 11), - FLUSH_SLAVE_TIMEOUT(2, 12), - MESSAGE_ILLEGAL(3, 13), - SERVICE_NOT_AVAILABLE(4, 14), - VERSION_NOT_SUPPORTED(5, 15), - NO_PERMISSION(6, 16), - TOPIC_NOT_EXIST(7, 17), - TOPIC_EXIST_ALREADY(8, 18), - PULL_NOT_FOUND(9, 19), - PULL_RETRY_IMMEDIATELY(10, 20), - PULL_OFFSET_MOVED(11, 21), - QUERY_NOT_FOUND(12, 22), - DELETE_INVALID_CONF(13, 100), - NOT_MERGE_CONF(14, 101), - REGISTER_BROKER_FAIL(15, 102), - REGISTER_BROKER_TIMEOUT(16, 103), - REGISTER_ORDER_TOPIC_FAIL(17, 104), - REGISTER_ORDER_TOPIC_TIMEOUT(18, 105), - UNREGISTER_BROKER_FAIL(19, 106), - UNREGISTER_BROKER_TIMEOUT(20, 107), - UNREGISTER_ORDER_TOPIC_TIMEOUT(21, 108), - TRANSACTION_SHOULD_COMMIT(22, 200), - TRANSACTION_SHOULD_ROLLBACK(23, 201), - TRANSACTION_STATE_UNKNOW(24, 202), - TRANSACTION_STATE_GROUP_WRONG(25, 203), - ; - - public static final int FLUSH_DISK_TIMEOUT_VALUE = 10; - public static final int SLAVE_NOT_AVAILABLE_VALUE = 11; - public static final int FLUSH_SLAVE_TIMEOUT_VALUE = 12; - public static final int MESSAGE_ILLEGAL_VALUE = 13; - public static final int SERVICE_NOT_AVAILABLE_VALUE = 14; - public static final int VERSION_NOT_SUPPORTED_VALUE = 15; - public static final int NO_PERMISSION_VALUE = 16; - public static final int TOPIC_NOT_EXIST_VALUE = 17; - public static final int TOPIC_EXIST_ALREADY_VALUE = 18; - public static final int PULL_NOT_FOUND_VALUE = 19; - public static final int PULL_RETRY_IMMEDIATELY_VALUE = 20; - public static final int PULL_OFFSET_MOVED_VALUE = 21; - public static final int QUERY_NOT_FOUND_VALUE = 22; - public static final int DELETE_INVALID_CONF_VALUE = 100; - public static final int NOT_MERGE_CONF_VALUE = 101; - public static final int REGISTER_BROKER_FAIL_VALUE = 102; - public static final int REGISTER_BROKER_TIMEOUT_VALUE = 103; - public static final int REGISTER_ORDER_TOPIC_FAIL_VALUE = 104; - public static final int REGISTER_ORDER_TOPIC_TIMEOUT_VALUE = 105; - public static final int UNREGISTER_BROKER_FAIL_VALUE = 106; - public static final int UNREGISTER_BROKER_TIMEOUT_VALUE = 107; - public static final int UNREGISTER_ORDER_TOPIC_TIMEOUT_VALUE = 108; - public static final int TRANSACTION_SHOULD_COMMIT_VALUE = 200; - public static final int TRANSACTION_SHOULD_ROLLBACK_VALUE = 201; - public static final int TRANSACTION_STATE_UNKNOW_VALUE = 202; - public static final int TRANSACTION_STATE_GROUP_WRONG_VALUE = 203; - - - public final int getNumber() { return value; } - - public static MQResponseCode valueOf(int value) { - switch (value) { - case 10: return FLUSH_DISK_TIMEOUT; - case 11: return SLAVE_NOT_AVAILABLE; - case 12: return FLUSH_SLAVE_TIMEOUT; - case 13: return MESSAGE_ILLEGAL; - case 14: return SERVICE_NOT_AVAILABLE; - case 15: return VERSION_NOT_SUPPORTED; - case 16: return NO_PERMISSION; - case 17: return TOPIC_NOT_EXIST; - case 18: return TOPIC_EXIST_ALREADY; - case 19: return PULL_NOT_FOUND; - case 20: return PULL_RETRY_IMMEDIATELY; - case 21: return PULL_OFFSET_MOVED; - case 22: return QUERY_NOT_FOUND; - case 100: return DELETE_INVALID_CONF; - case 101: return NOT_MERGE_CONF; - case 102: return REGISTER_BROKER_FAIL; - case 103: return REGISTER_BROKER_TIMEOUT; - case 104: return REGISTER_ORDER_TOPIC_FAIL; - case 105: return REGISTER_ORDER_TOPIC_TIMEOUT; - case 106: return UNREGISTER_BROKER_FAIL; - case 107: return UNREGISTER_BROKER_TIMEOUT; - case 108: return UNREGISTER_ORDER_TOPIC_TIMEOUT; - case 200: return TRANSACTION_SHOULD_COMMIT; - case 201: return TRANSACTION_SHOULD_ROLLBACK; - case 202: return TRANSACTION_STATE_UNKNOW; - case 203: return TRANSACTION_STATE_GROUP_WRONG; - default: return null; - } - } - - public static com.google.protobuf.Internal.EnumLiteMap - internalGetValueMap() { - return internalValueMap; - } - private static com.google.protobuf.Internal.EnumLiteMap - internalValueMap = - new com.google.protobuf.Internal.EnumLiteMap() { - public MQResponseCode findValueByNumber(int number) { - return MQResponseCode.valueOf(number); - } - }; - - public final com.google.protobuf.Descriptors.EnumValueDescriptor - getValueDescriptor() { - return getDescriptor().getValues().get(index); - } - public final com.google.protobuf.Descriptors.EnumDescriptor - getDescriptorForType() { - return getDescriptor(); - } - public static final com.google.protobuf.Descriptors.EnumDescriptor - getDescriptor() { - return com.alibaba.rocketmq.common.protocol.MQProtos.getDescriptor().getEnumTypes().get(1); - } - - private static final MQResponseCode[] VALUES = { - FLUSH_DISK_TIMEOUT, SLAVE_NOT_AVAILABLE, FLUSH_SLAVE_TIMEOUT, MESSAGE_ILLEGAL, SERVICE_NOT_AVAILABLE, VERSION_NOT_SUPPORTED, NO_PERMISSION, TOPIC_NOT_EXIST, TOPIC_EXIST_ALREADY, PULL_NOT_FOUND, PULL_RETRY_IMMEDIATELY, PULL_OFFSET_MOVED, QUERY_NOT_FOUND, DELETE_INVALID_CONF, NOT_MERGE_CONF, REGISTER_BROKER_FAIL, REGISTER_BROKER_TIMEOUT, REGISTER_ORDER_TOPIC_FAIL, REGISTER_ORDER_TOPIC_TIMEOUT, UNREGISTER_BROKER_FAIL, UNREGISTER_BROKER_TIMEOUT, UNREGISTER_ORDER_TOPIC_TIMEOUT, TRANSACTION_SHOULD_COMMIT, TRANSACTION_SHOULD_ROLLBACK, TRANSACTION_STATE_UNKNOW, TRANSACTION_STATE_GROUP_WRONG, - }; - - public static MQResponseCode valueOf( - com.google.protobuf.Descriptors.EnumValueDescriptor desc) { - if (desc.getType() != getDescriptor()) { - throw new java.lang.IllegalArgumentException( - "EnumValueDescriptor is not for this type."); - } - return VALUES[desc.getIndex()]; - } - - private final int index; - private final int value; - - private MQResponseCode(int index, int value) { - this.index = index; - this.value = value; - } - - // @@protoc_insertion_point(enum_scope:rocketmq.MQResponseCode) - } - - public interface BrokerInfoOrBuilder - extends com.google.protobuf.MessageOrBuilder { - - // required string brokerName = 1; - boolean hasBrokerName(); - String getBrokerName(); - - // repeated .rocketmq.BrokerInfo.BrokerAddr brokerAddrs = 2; - java.util.List - getBrokerAddrsList(); - com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo.BrokerAddr getBrokerAddrs(int index); - int getBrokerAddrsCount(); - java.util.List - getBrokerAddrsOrBuilderList(); - com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo.BrokerAddrOrBuilder getBrokerAddrsOrBuilder( - int index); - } - public static final class BrokerInfo extends - com.google.protobuf.GeneratedMessage - implements BrokerInfoOrBuilder { - // Use BrokerInfo.newBuilder() to construct. - private BrokerInfo(Builder builder) { - super(builder); - } - private BrokerInfo(boolean noInit) {} - - private static final BrokerInfo defaultInstance; - public static BrokerInfo getDefaultInstance() { - return defaultInstance; - } - - public BrokerInfo getDefaultInstanceForType() { - return defaultInstance; - } - - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return com.alibaba.rocketmq.common.protocol.MQProtos.internal_static_rocketmq_BrokerInfo_descriptor; - } - - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return com.alibaba.rocketmq.common.protocol.MQProtos.internal_static_rocketmq_BrokerInfo_fieldAccessorTable; - } - - public interface BrokerAddrOrBuilder - extends com.google.protobuf.MessageOrBuilder { - - // required int64 id = 1; - boolean hasId(); - long getId(); - - // required string addr = 2; - boolean hasAddr(); - String getAddr(); - } - public static final class BrokerAddr extends - com.google.protobuf.GeneratedMessage - implements BrokerAddrOrBuilder { - // Use BrokerAddr.newBuilder() to construct. - private BrokerAddr(Builder builder) { - super(builder); - } - private BrokerAddr(boolean noInit) {} - - private static final BrokerAddr defaultInstance; - public static BrokerAddr getDefaultInstance() { - return defaultInstance; - } - - public BrokerAddr getDefaultInstanceForType() { - return defaultInstance; - } - - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return com.alibaba.rocketmq.common.protocol.MQProtos.internal_static_rocketmq_BrokerInfo_BrokerAddr_descriptor; - } - - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return com.alibaba.rocketmq.common.protocol.MQProtos.internal_static_rocketmq_BrokerInfo_BrokerAddr_fieldAccessorTable; - } - - private int bitField0_; - // required int64 id = 1; - public static final int ID_FIELD_NUMBER = 1; - private long id_; - public boolean hasId() { - return ((bitField0_ & 0x00000001) == 0x00000001); - } - public long getId() { - return id_; - } - - // required string addr = 2; - public static final int ADDR_FIELD_NUMBER = 2; - private java.lang.Object addr_; - public boolean hasAddr() { - return ((bitField0_ & 0x00000002) == 0x00000002); - } - public String getAddr() { - java.lang.Object ref = addr_; - if (ref instanceof String) { - return (String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - String s = bs.toStringUtf8(); - if (com.google.protobuf.Internal.isValidUtf8(bs)) { - addr_ = s; - } - return s; - } - } - private com.google.protobuf.ByteString getAddrBytes() { - java.lang.Object ref = addr_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8((String) ref); - addr_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - private void initFields() { - id_ = 0L; - addr_ = ""; - } - private byte memoizedIsInitialized = -1; - public final boolean isInitialized() { - byte isInitialized = memoizedIsInitialized; - if (isInitialized != -1) return isInitialized == 1; - - if (!hasId()) { - memoizedIsInitialized = 0; - return false; - } - if (!hasAddr()) { - memoizedIsInitialized = 0; - return false; - } - memoizedIsInitialized = 1; - return true; - } - - public void writeTo(com.google.protobuf.CodedOutputStream output) - throws java.io.IOException { - getSerializedSize(); - if (((bitField0_ & 0x00000001) == 0x00000001)) { - output.writeInt64(1, id_); - } - if (((bitField0_ & 0x00000002) == 0x00000002)) { - output.writeBytes(2, getAddrBytes()); - } - getUnknownFields().writeTo(output); - } - - private int memoizedSerializedSize = -1; - public int getSerializedSize() { - int size = memoizedSerializedSize; - if (size != -1) return size; - - size = 0; - if (((bitField0_ & 0x00000001) == 0x00000001)) { - size += com.google.protobuf.CodedOutputStream - .computeInt64Size(1, id_); - } - if (((bitField0_ & 0x00000002) == 0x00000002)) { - size += com.google.protobuf.CodedOutputStream - .computeBytesSize(2, getAddrBytes()); - } - size += getUnknownFields().getSerializedSize(); - memoizedSerializedSize = size; - return size; - } - - private static final long serialVersionUID = 0L; - @java.lang.Override - protected java.lang.Object writeReplace() - throws java.io.ObjectStreamException { - return super.writeReplace(); - } - - public static com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo.BrokerAddr parseFrom( - com.google.protobuf.ByteString data) - throws com.google.protobuf.InvalidProtocolBufferException { - return newBuilder().mergeFrom(data).buildParsed(); - } - public static com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo.BrokerAddr parseFrom( - com.google.protobuf.ByteString data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return newBuilder().mergeFrom(data, extensionRegistry) - .buildParsed(); - } - public static com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo.BrokerAddr parseFrom(byte[] data) - throws com.google.protobuf.InvalidProtocolBufferException { - return newBuilder().mergeFrom(data).buildParsed(); - } - public static com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo.BrokerAddr parseFrom( - byte[] data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return newBuilder().mergeFrom(data, extensionRegistry) - .buildParsed(); - } - public static com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo.BrokerAddr parseFrom(java.io.InputStream input) - throws java.io.IOException { - return newBuilder().mergeFrom(input).buildParsed(); - } - public static com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo.BrokerAddr parseFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return newBuilder().mergeFrom(input, extensionRegistry) - .buildParsed(); - } - public static com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo.BrokerAddr parseDelimitedFrom(java.io.InputStream input) - throws java.io.IOException { - Builder builder = newBuilder(); - if (builder.mergeDelimitedFrom(input)) { - return builder.buildParsed(); - } else { - return null; - } - } - public static com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo.BrokerAddr parseDelimitedFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - Builder builder = newBuilder(); - if (builder.mergeDelimitedFrom(input, extensionRegistry)) { - return builder.buildParsed(); - } else { - return null; - } - } - public static com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo.BrokerAddr parseFrom( - com.google.protobuf.CodedInputStream input) - throws java.io.IOException { - return newBuilder().mergeFrom(input).buildParsed(); - } - public static com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo.BrokerAddr parseFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return newBuilder().mergeFrom(input, extensionRegistry) - .buildParsed(); - } - - public static Builder newBuilder() { return Builder.create(); } - public Builder newBuilderForType() { return newBuilder(); } - public static Builder newBuilder(com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo.BrokerAddr prototype) { - return newBuilder().mergeFrom(prototype); - } - public Builder toBuilder() { return newBuilder(this); } - - @java.lang.Override - protected Builder newBuilderForType( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - Builder builder = new Builder(parent); - return builder; - } - public static final class Builder extends - com.google.protobuf.GeneratedMessage.Builder - implements com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo.BrokerAddrOrBuilder { - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return com.alibaba.rocketmq.common.protocol.MQProtos.internal_static_rocketmq_BrokerInfo_BrokerAddr_descriptor; - } - - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return com.alibaba.rocketmq.common.protocol.MQProtos.internal_static_rocketmq_BrokerInfo_BrokerAddr_fieldAccessorTable; - } - - // Construct using com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo.BrokerAddr.newBuilder() - private Builder() { - maybeForceBuilderInitialization(); - } - - private Builder(BuilderParent parent) { - super(parent); - maybeForceBuilderInitialization(); - } - private void maybeForceBuilderInitialization() { - if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) { - } - } - private static Builder create() { - return new Builder(); - } - - public Builder clear() { - super.clear(); - id_ = 0L; - bitField0_ = (bitField0_ & ~0x00000001); - addr_ = ""; - bitField0_ = (bitField0_ & ~0x00000002); - return this; - } - - public Builder clone() { - return create().mergeFrom(buildPartial()); - } - - public com.google.protobuf.Descriptors.Descriptor - getDescriptorForType() { - return com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo.BrokerAddr.getDescriptor(); - } - - public com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo.BrokerAddr getDefaultInstanceForType() { - return com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo.BrokerAddr.getDefaultInstance(); - } - - public com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo.BrokerAddr build() { - com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo.BrokerAddr result = buildPartial(); - if (!result.isInitialized()) { - throw newUninitializedMessageException(result); - } - return result; - } - - private com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo.BrokerAddr buildParsed() - throws com.google.protobuf.InvalidProtocolBufferException { - com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo.BrokerAddr result = buildPartial(); - if (!result.isInitialized()) { - throw newUninitializedMessageException( - result).asInvalidProtocolBufferException(); - } - return result; - } - - public com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo.BrokerAddr buildPartial() { - com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo.BrokerAddr result = new com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo.BrokerAddr(this); - int from_bitField0_ = bitField0_; - int to_bitField0_ = 0; - if (((from_bitField0_ & 0x00000001) == 0x00000001)) { - to_bitField0_ |= 0x00000001; - } - result.id_ = id_; - if (((from_bitField0_ & 0x00000002) == 0x00000002)) { - to_bitField0_ |= 0x00000002; - } - result.addr_ = addr_; - result.bitField0_ = to_bitField0_; - onBuilt(); - return result; - } - - public Builder mergeFrom(com.google.protobuf.Message other) { - if (other instanceof com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo.BrokerAddr) { - return mergeFrom((com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo.BrokerAddr)other); - } else { - super.mergeFrom(other); - return this; - } - } - - public Builder mergeFrom(com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo.BrokerAddr other) { - if (other == com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo.BrokerAddr.getDefaultInstance()) return this; - if (other.hasId()) { - setId(other.getId()); - } - if (other.hasAddr()) { - setAddr(other.getAddr()); - } - this.mergeUnknownFields(other.getUnknownFields()); - return this; - } - - public final boolean isInitialized() { - if (!hasId()) { - - return false; - } - if (!hasAddr()) { - - return false; - } - return true; - } - - public Builder mergeFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - com.google.protobuf.UnknownFieldSet.Builder unknownFields = - com.google.protobuf.UnknownFieldSet.newBuilder( - this.getUnknownFields()); - while (true) { - int tag = input.readTag(); - switch (tag) { - case 0: - this.setUnknownFields(unknownFields.build()); - onChanged(); - return this; - default: { - if (!parseUnknownField(input, unknownFields, - extensionRegistry, tag)) { - this.setUnknownFields(unknownFields.build()); - onChanged(); - return this; - } - break; - } - case 8: { - bitField0_ |= 0x00000001; - id_ = input.readInt64(); - break; - } - case 18: { - bitField0_ |= 0x00000002; - addr_ = input.readBytes(); - break; - } - } - } - } - - private int bitField0_; - - // required int64 id = 1; - private long id_ ; - public boolean hasId() { - return ((bitField0_ & 0x00000001) == 0x00000001); - } - public long getId() { - return id_; - } - public Builder setId(long value) { - bitField0_ |= 0x00000001; - id_ = value; - onChanged(); - return this; - } - public Builder clearId() { - bitField0_ = (bitField0_ & ~0x00000001); - id_ = 0L; - onChanged(); - return this; - } - - // required string addr = 2; - private java.lang.Object addr_ = ""; - public boolean hasAddr() { - return ((bitField0_ & 0x00000002) == 0x00000002); - } - public String getAddr() { - java.lang.Object ref = addr_; - if (!(ref instanceof String)) { - String s = ((com.google.protobuf.ByteString) ref).toStringUtf8(); - addr_ = s; - return s; - } else { - return (String) ref; - } - } - public Builder setAddr(String value) { - if (value == null) { - throw new NullPointerException(); - } - bitField0_ |= 0x00000002; - addr_ = value; - onChanged(); - return this; - } - public Builder clearAddr() { - bitField0_ = (bitField0_ & ~0x00000002); - addr_ = getDefaultInstance().getAddr(); - onChanged(); - return this; - } - void setAddr(com.google.protobuf.ByteString value) { - bitField0_ |= 0x00000002; - addr_ = value; - onChanged(); - } - - // @@protoc_insertion_point(builder_scope:rocketmq.BrokerInfo.BrokerAddr) - } - - static { - defaultInstance = new BrokerAddr(true); - defaultInstance.initFields(); - } - - // @@protoc_insertion_point(class_scope:rocketmq.BrokerInfo.BrokerAddr) - } - - private int bitField0_; - // required string brokerName = 1; - public static final int BROKERNAME_FIELD_NUMBER = 1; - private java.lang.Object brokerName_; - public boolean hasBrokerName() { - return ((bitField0_ & 0x00000001) == 0x00000001); - } - public String getBrokerName() { - java.lang.Object ref = brokerName_; - if (ref instanceof String) { - return (String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - String s = bs.toStringUtf8(); - if (com.google.protobuf.Internal.isValidUtf8(bs)) { - brokerName_ = s; - } - return s; - } - } - private com.google.protobuf.ByteString getBrokerNameBytes() { - java.lang.Object ref = brokerName_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8((String) ref); - brokerName_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - // repeated .rocketmq.BrokerInfo.BrokerAddr brokerAddrs = 2; - public static final int BROKERADDRS_FIELD_NUMBER = 2; - private java.util.List brokerAddrs_; - public java.util.List getBrokerAddrsList() { - return brokerAddrs_; - } - public java.util.List - getBrokerAddrsOrBuilderList() { - return brokerAddrs_; - } - public int getBrokerAddrsCount() { - return brokerAddrs_.size(); - } - public com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo.BrokerAddr getBrokerAddrs(int index) { - return brokerAddrs_.get(index); - } - public com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo.BrokerAddrOrBuilder getBrokerAddrsOrBuilder( - int index) { - return brokerAddrs_.get(index); - } - - private void initFields() { - brokerName_ = ""; - brokerAddrs_ = java.util.Collections.emptyList(); - } - private byte memoizedIsInitialized = -1; - public final boolean isInitialized() { - byte isInitialized = memoizedIsInitialized; - if (isInitialized != -1) return isInitialized == 1; - - if (!hasBrokerName()) { - memoizedIsInitialized = 0; - return false; - } - for (int i = 0; i < getBrokerAddrsCount(); i++) { - if (!getBrokerAddrs(i).isInitialized()) { - memoizedIsInitialized = 0; - return false; - } - } - memoizedIsInitialized = 1; - return true; - } - - public void writeTo(com.google.protobuf.CodedOutputStream output) - throws java.io.IOException { - getSerializedSize(); - if (((bitField0_ & 0x00000001) == 0x00000001)) { - output.writeBytes(1, getBrokerNameBytes()); - } - for (int i = 0; i < brokerAddrs_.size(); i++) { - output.writeMessage(2, brokerAddrs_.get(i)); - } - getUnknownFields().writeTo(output); - } - - private int memoizedSerializedSize = -1; - public int getSerializedSize() { - int size = memoizedSerializedSize; - if (size != -1) return size; - - size = 0; - if (((bitField0_ & 0x00000001) == 0x00000001)) { - size += com.google.protobuf.CodedOutputStream - .computeBytesSize(1, getBrokerNameBytes()); - } - for (int i = 0; i < brokerAddrs_.size(); i++) { - size += com.google.protobuf.CodedOutputStream - .computeMessageSize(2, brokerAddrs_.get(i)); - } - size += getUnknownFields().getSerializedSize(); - memoizedSerializedSize = size; - return size; - } - - private static final long serialVersionUID = 0L; - @java.lang.Override - protected java.lang.Object writeReplace() - throws java.io.ObjectStreamException { - return super.writeReplace(); - } - - public static com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo parseFrom( - com.google.protobuf.ByteString data) - throws com.google.protobuf.InvalidProtocolBufferException { - return newBuilder().mergeFrom(data).buildParsed(); - } - public static com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo parseFrom( - com.google.protobuf.ByteString data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return newBuilder().mergeFrom(data, extensionRegistry) - .buildParsed(); - } - public static com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo parseFrom(byte[] data) - throws com.google.protobuf.InvalidProtocolBufferException { - return newBuilder().mergeFrom(data).buildParsed(); - } - public static com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo parseFrom( - byte[] data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return newBuilder().mergeFrom(data, extensionRegistry) - .buildParsed(); - } - public static com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo parseFrom(java.io.InputStream input) - throws java.io.IOException { - return newBuilder().mergeFrom(input).buildParsed(); - } - public static com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo parseFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return newBuilder().mergeFrom(input, extensionRegistry) - .buildParsed(); - } - public static com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo parseDelimitedFrom(java.io.InputStream input) - throws java.io.IOException { - Builder builder = newBuilder(); - if (builder.mergeDelimitedFrom(input)) { - return builder.buildParsed(); - } else { - return null; - } - } - public static com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo parseDelimitedFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - Builder builder = newBuilder(); - if (builder.mergeDelimitedFrom(input, extensionRegistry)) { - return builder.buildParsed(); - } else { - return null; - } - } - public static com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo parseFrom( - com.google.protobuf.CodedInputStream input) - throws java.io.IOException { - return newBuilder().mergeFrom(input).buildParsed(); - } - public static com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo parseFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return newBuilder().mergeFrom(input, extensionRegistry) - .buildParsed(); - } - - public static Builder newBuilder() { return Builder.create(); } - public Builder newBuilderForType() { return newBuilder(); } - public static Builder newBuilder(com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo prototype) { - return newBuilder().mergeFrom(prototype); - } - public Builder toBuilder() { return newBuilder(this); } - - @java.lang.Override - protected Builder newBuilderForType( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - Builder builder = new Builder(parent); - return builder; - } - public static final class Builder extends - com.google.protobuf.GeneratedMessage.Builder - implements com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfoOrBuilder { - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return com.alibaba.rocketmq.common.protocol.MQProtos.internal_static_rocketmq_BrokerInfo_descriptor; - } - - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return com.alibaba.rocketmq.common.protocol.MQProtos.internal_static_rocketmq_BrokerInfo_fieldAccessorTable; - } - - // Construct using com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo.newBuilder() - private Builder() { - maybeForceBuilderInitialization(); - } - - private Builder(BuilderParent parent) { - super(parent); - maybeForceBuilderInitialization(); - } - private void maybeForceBuilderInitialization() { - if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) { - getBrokerAddrsFieldBuilder(); - } - } - private static Builder create() { - return new Builder(); - } - - public Builder clear() { - super.clear(); - brokerName_ = ""; - bitField0_ = (bitField0_ & ~0x00000001); - if (brokerAddrsBuilder_ == null) { - brokerAddrs_ = java.util.Collections.emptyList(); - bitField0_ = (bitField0_ & ~0x00000002); - } else { - brokerAddrsBuilder_.clear(); - } - return this; - } - - public Builder clone() { - return create().mergeFrom(buildPartial()); - } - - public com.google.protobuf.Descriptors.Descriptor - getDescriptorForType() { - return com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo.getDescriptor(); - } - - public com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo getDefaultInstanceForType() { - return com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo.getDefaultInstance(); - } - - public com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo build() { - com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo result = buildPartial(); - if (!result.isInitialized()) { - throw newUninitializedMessageException(result); - } - return result; - } - - private com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo buildParsed() - throws com.google.protobuf.InvalidProtocolBufferException { - com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo result = buildPartial(); - if (!result.isInitialized()) { - throw newUninitializedMessageException( - result).asInvalidProtocolBufferException(); - } - return result; - } - - public com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo buildPartial() { - com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo result = new com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo(this); - int from_bitField0_ = bitField0_; - int to_bitField0_ = 0; - if (((from_bitField0_ & 0x00000001) == 0x00000001)) { - to_bitField0_ |= 0x00000001; - } - result.brokerName_ = brokerName_; - if (brokerAddrsBuilder_ == null) { - if (((bitField0_ & 0x00000002) == 0x00000002)) { - brokerAddrs_ = java.util.Collections.unmodifiableList(brokerAddrs_); - bitField0_ = (bitField0_ & ~0x00000002); - } - result.brokerAddrs_ = brokerAddrs_; - } else { - result.brokerAddrs_ = brokerAddrsBuilder_.build(); - } - result.bitField0_ = to_bitField0_; - onBuilt(); - return result; - } - - public Builder mergeFrom(com.google.protobuf.Message other) { - if (other instanceof com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo) { - return mergeFrom((com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo)other); - } else { - super.mergeFrom(other); - return this; - } - } - - public Builder mergeFrom(com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo other) { - if (other == com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo.getDefaultInstance()) return this; - if (other.hasBrokerName()) { - setBrokerName(other.getBrokerName()); - } - if (brokerAddrsBuilder_ == null) { - if (!other.brokerAddrs_.isEmpty()) { - if (brokerAddrs_.isEmpty()) { - brokerAddrs_ = other.brokerAddrs_; - bitField0_ = (bitField0_ & ~0x00000002); - } else { - ensureBrokerAddrsIsMutable(); - brokerAddrs_.addAll(other.brokerAddrs_); - } - onChanged(); - } - } else { - if (!other.brokerAddrs_.isEmpty()) { - if (brokerAddrsBuilder_.isEmpty()) { - brokerAddrsBuilder_.dispose(); - brokerAddrsBuilder_ = null; - brokerAddrs_ = other.brokerAddrs_; - bitField0_ = (bitField0_ & ~0x00000002); - brokerAddrsBuilder_ = - com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders ? - getBrokerAddrsFieldBuilder() : null; - } else { - brokerAddrsBuilder_.addAllMessages(other.brokerAddrs_); - } - } - } - this.mergeUnknownFields(other.getUnknownFields()); - return this; - } - - public final boolean isInitialized() { - if (!hasBrokerName()) { - - return false; - } - for (int i = 0; i < getBrokerAddrsCount(); i++) { - if (!getBrokerAddrs(i).isInitialized()) { - - return false; - } - } - return true; - } - - public Builder mergeFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - com.google.protobuf.UnknownFieldSet.Builder unknownFields = - com.google.protobuf.UnknownFieldSet.newBuilder( - this.getUnknownFields()); - while (true) { - int tag = input.readTag(); - switch (tag) { - case 0: - this.setUnknownFields(unknownFields.build()); - onChanged(); - return this; - default: { - if (!parseUnknownField(input, unknownFields, - extensionRegistry, tag)) { - this.setUnknownFields(unknownFields.build()); - onChanged(); - return this; - } - break; - } - case 10: { - bitField0_ |= 0x00000001; - brokerName_ = input.readBytes(); - break; - } - case 18: { - com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo.BrokerAddr.Builder subBuilder = com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo.BrokerAddr.newBuilder(); - input.readMessage(subBuilder, extensionRegistry); - addBrokerAddrs(subBuilder.buildPartial()); - break; - } - } - } - } - - private int bitField0_; - - // required string brokerName = 1; - private java.lang.Object brokerName_ = ""; - public boolean hasBrokerName() { - return ((bitField0_ & 0x00000001) == 0x00000001); - } - public String getBrokerName() { - java.lang.Object ref = brokerName_; - if (!(ref instanceof String)) { - String s = ((com.google.protobuf.ByteString) ref).toStringUtf8(); - brokerName_ = s; - return s; - } else { - return (String) ref; - } - } - public Builder setBrokerName(String value) { - if (value == null) { - throw new NullPointerException(); - } - bitField0_ |= 0x00000001; - brokerName_ = value; - onChanged(); - return this; - } - public Builder clearBrokerName() { - bitField0_ = (bitField0_ & ~0x00000001); - brokerName_ = getDefaultInstance().getBrokerName(); - onChanged(); - return this; - } - void setBrokerName(com.google.protobuf.ByteString value) { - bitField0_ |= 0x00000001; - brokerName_ = value; - onChanged(); - } - - // repeated .rocketmq.BrokerInfo.BrokerAddr brokerAddrs = 2; - private java.util.List brokerAddrs_ = - java.util.Collections.emptyList(); - private void ensureBrokerAddrsIsMutable() { - if (!((bitField0_ & 0x00000002) == 0x00000002)) { - brokerAddrs_ = new java.util.ArrayList(brokerAddrs_); - bitField0_ |= 0x00000002; - } - } - - private com.google.protobuf.RepeatedFieldBuilder< - com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo.BrokerAddr, com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo.BrokerAddr.Builder, com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo.BrokerAddrOrBuilder> brokerAddrsBuilder_; - - public java.util.List getBrokerAddrsList() { - if (brokerAddrsBuilder_ == null) { - return java.util.Collections.unmodifiableList(brokerAddrs_); - } else { - return brokerAddrsBuilder_.getMessageList(); - } - } - public int getBrokerAddrsCount() { - if (brokerAddrsBuilder_ == null) { - return brokerAddrs_.size(); - } else { - return brokerAddrsBuilder_.getCount(); - } - } - public com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo.BrokerAddr getBrokerAddrs(int index) { - if (brokerAddrsBuilder_ == null) { - return brokerAddrs_.get(index); - } else { - return brokerAddrsBuilder_.getMessage(index); - } - } - public Builder setBrokerAddrs( - int index, com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo.BrokerAddr value) { - if (brokerAddrsBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - ensureBrokerAddrsIsMutable(); - brokerAddrs_.set(index, value); - onChanged(); - } else { - brokerAddrsBuilder_.setMessage(index, value); - } - return this; - } - public Builder setBrokerAddrs( - int index, com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo.BrokerAddr.Builder builderForValue) { - if (brokerAddrsBuilder_ == null) { - ensureBrokerAddrsIsMutable(); - brokerAddrs_.set(index, builderForValue.build()); - onChanged(); - } else { - brokerAddrsBuilder_.setMessage(index, builderForValue.build()); - } - return this; - } - public Builder addBrokerAddrs(com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo.BrokerAddr value) { - if (brokerAddrsBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - ensureBrokerAddrsIsMutable(); - brokerAddrs_.add(value); - onChanged(); - } else { - brokerAddrsBuilder_.addMessage(value); - } - return this; - } - public Builder addBrokerAddrs( - int index, com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo.BrokerAddr value) { - if (brokerAddrsBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - ensureBrokerAddrsIsMutable(); - brokerAddrs_.add(index, value); - onChanged(); - } else { - brokerAddrsBuilder_.addMessage(index, value); - } - return this; - } - public Builder addBrokerAddrs( - com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo.BrokerAddr.Builder builderForValue) { - if (brokerAddrsBuilder_ == null) { - ensureBrokerAddrsIsMutable(); - brokerAddrs_.add(builderForValue.build()); - onChanged(); - } else { - brokerAddrsBuilder_.addMessage(builderForValue.build()); - } - return this; - } - public Builder addBrokerAddrs( - int index, com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo.BrokerAddr.Builder builderForValue) { - if (brokerAddrsBuilder_ == null) { - ensureBrokerAddrsIsMutable(); - brokerAddrs_.add(index, builderForValue.build()); - onChanged(); - } else { - brokerAddrsBuilder_.addMessage(index, builderForValue.build()); - } - return this; - } - public Builder addAllBrokerAddrs( - java.lang.Iterable values) { - if (brokerAddrsBuilder_ == null) { - ensureBrokerAddrsIsMutable(); - super.addAll(values, brokerAddrs_); - onChanged(); - } else { - brokerAddrsBuilder_.addAllMessages(values); - } - return this; - } - public Builder clearBrokerAddrs() { - if (brokerAddrsBuilder_ == null) { - brokerAddrs_ = java.util.Collections.emptyList(); - bitField0_ = (bitField0_ & ~0x00000002); - onChanged(); - } else { - brokerAddrsBuilder_.clear(); - } - return this; - } - public Builder removeBrokerAddrs(int index) { - if (brokerAddrsBuilder_ == null) { - ensureBrokerAddrsIsMutable(); - brokerAddrs_.remove(index); - onChanged(); - } else { - brokerAddrsBuilder_.remove(index); - } - return this; - } - public com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo.BrokerAddr.Builder getBrokerAddrsBuilder( - int index) { - return getBrokerAddrsFieldBuilder().getBuilder(index); - } - public com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo.BrokerAddrOrBuilder getBrokerAddrsOrBuilder( - int index) { - if (brokerAddrsBuilder_ == null) { - return brokerAddrs_.get(index); } else { - return brokerAddrsBuilder_.getMessageOrBuilder(index); - } - } - public java.util.List - getBrokerAddrsOrBuilderList() { - if (brokerAddrsBuilder_ != null) { - return brokerAddrsBuilder_.getMessageOrBuilderList(); - } else { - return java.util.Collections.unmodifiableList(brokerAddrs_); - } - } - public com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo.BrokerAddr.Builder addBrokerAddrsBuilder() { - return getBrokerAddrsFieldBuilder().addBuilder( - com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo.BrokerAddr.getDefaultInstance()); - } - public com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo.BrokerAddr.Builder addBrokerAddrsBuilder( - int index) { - return getBrokerAddrsFieldBuilder().addBuilder( - index, com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo.BrokerAddr.getDefaultInstance()); - } - public java.util.List - getBrokerAddrsBuilderList() { - return getBrokerAddrsFieldBuilder().getBuilderList(); - } - private com.google.protobuf.RepeatedFieldBuilder< - com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo.BrokerAddr, com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo.BrokerAddr.Builder, com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo.BrokerAddrOrBuilder> - getBrokerAddrsFieldBuilder() { - if (brokerAddrsBuilder_ == null) { - brokerAddrsBuilder_ = new com.google.protobuf.RepeatedFieldBuilder< - com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo.BrokerAddr, com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo.BrokerAddr.Builder, com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo.BrokerAddrOrBuilder>( - brokerAddrs_, - ((bitField0_ & 0x00000002) == 0x00000002), - getParentForChildren(), - isClean()); - brokerAddrs_ = null; - } - return brokerAddrsBuilder_; - } - - // @@protoc_insertion_point(builder_scope:rocketmq.BrokerInfo) - } - - static { - defaultInstance = new BrokerInfo(true); - defaultInstance.initFields(); - } - - // @@protoc_insertion_point(class_scope:rocketmq.BrokerInfo) - } - - public interface QueueInfoOrBuilder - extends com.google.protobuf.MessageOrBuilder { - - // required string brokerName = 1; - boolean hasBrokerName(); - String getBrokerName(); - - // required int32 readQueueNums = 2; - boolean hasReadQueueNums(); - int getReadQueueNums(); - - // required int32 writeQueueNums = 3; - boolean hasWriteQueueNums(); - int getWriteQueueNums(); - - // required int32 perm = 4; - boolean hasPerm(); - int getPerm(); - } - public static final class QueueInfo extends - com.google.protobuf.GeneratedMessage - implements QueueInfoOrBuilder { - // Use QueueInfo.newBuilder() to construct. - private QueueInfo(Builder builder) { - super(builder); - } - private QueueInfo(boolean noInit) {} - - private static final QueueInfo defaultInstance; - public static QueueInfo getDefaultInstance() { - return defaultInstance; - } - - public QueueInfo getDefaultInstanceForType() { - return defaultInstance; - } - - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return com.alibaba.rocketmq.common.protocol.MQProtos.internal_static_rocketmq_QueueInfo_descriptor; - } - - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return com.alibaba.rocketmq.common.protocol.MQProtos.internal_static_rocketmq_QueueInfo_fieldAccessorTable; - } - - private int bitField0_; - // required string brokerName = 1; - public static final int BROKERNAME_FIELD_NUMBER = 1; - private java.lang.Object brokerName_; - public boolean hasBrokerName() { - return ((bitField0_ & 0x00000001) == 0x00000001); - } - public String getBrokerName() { - java.lang.Object ref = brokerName_; - if (ref instanceof String) { - return (String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - String s = bs.toStringUtf8(); - if (com.google.protobuf.Internal.isValidUtf8(bs)) { - brokerName_ = s; - } - return s; - } - } - private com.google.protobuf.ByteString getBrokerNameBytes() { - java.lang.Object ref = brokerName_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8((String) ref); - brokerName_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - // required int32 readQueueNums = 2; - public static final int READQUEUENUMS_FIELD_NUMBER = 2; - private int readQueueNums_; - public boolean hasReadQueueNums() { - return ((bitField0_ & 0x00000002) == 0x00000002); - } - public int getReadQueueNums() { - return readQueueNums_; - } - - // required int32 writeQueueNums = 3; - public static final int WRITEQUEUENUMS_FIELD_NUMBER = 3; - private int writeQueueNums_; - public boolean hasWriteQueueNums() { - return ((bitField0_ & 0x00000004) == 0x00000004); - } - public int getWriteQueueNums() { - return writeQueueNums_; - } - - // required int32 perm = 4; - public static final int PERM_FIELD_NUMBER = 4; - private int perm_; - public boolean hasPerm() { - return ((bitField0_ & 0x00000008) == 0x00000008); - } - public int getPerm() { - return perm_; - } - - private void initFields() { - brokerName_ = ""; - readQueueNums_ = 0; - writeQueueNums_ = 0; - perm_ = 0; - } - private byte memoizedIsInitialized = -1; - public final boolean isInitialized() { - byte isInitialized = memoizedIsInitialized; - if (isInitialized != -1) return isInitialized == 1; - - if (!hasBrokerName()) { - memoizedIsInitialized = 0; - return false; - } - if (!hasReadQueueNums()) { - memoizedIsInitialized = 0; - return false; - } - if (!hasWriteQueueNums()) { - memoizedIsInitialized = 0; - return false; - } - if (!hasPerm()) { - memoizedIsInitialized = 0; - return false; - } - memoizedIsInitialized = 1; - return true; - } - - public void writeTo(com.google.protobuf.CodedOutputStream output) - throws java.io.IOException { - getSerializedSize(); - if (((bitField0_ & 0x00000001) == 0x00000001)) { - output.writeBytes(1, getBrokerNameBytes()); - } - if (((bitField0_ & 0x00000002) == 0x00000002)) { - output.writeInt32(2, readQueueNums_); - } - if (((bitField0_ & 0x00000004) == 0x00000004)) { - output.writeInt32(3, writeQueueNums_); - } - if (((bitField0_ & 0x00000008) == 0x00000008)) { - output.writeInt32(4, perm_); - } - getUnknownFields().writeTo(output); - } - - private int memoizedSerializedSize = -1; - public int getSerializedSize() { - int size = memoizedSerializedSize; - if (size != -1) return size; - - size = 0; - if (((bitField0_ & 0x00000001) == 0x00000001)) { - size += com.google.protobuf.CodedOutputStream - .computeBytesSize(1, getBrokerNameBytes()); - } - if (((bitField0_ & 0x00000002) == 0x00000002)) { - size += com.google.protobuf.CodedOutputStream - .computeInt32Size(2, readQueueNums_); - } - if (((bitField0_ & 0x00000004) == 0x00000004)) { - size += com.google.protobuf.CodedOutputStream - .computeInt32Size(3, writeQueueNums_); - } - if (((bitField0_ & 0x00000008) == 0x00000008)) { - size += com.google.protobuf.CodedOutputStream - .computeInt32Size(4, perm_); - } - size += getUnknownFields().getSerializedSize(); - memoizedSerializedSize = size; - return size; - } - - private static final long serialVersionUID = 0L; - @java.lang.Override - protected java.lang.Object writeReplace() - throws java.io.ObjectStreamException { - return super.writeReplace(); - } - - public static com.alibaba.rocketmq.common.protocol.MQProtos.QueueInfo parseFrom( - com.google.protobuf.ByteString data) - throws com.google.protobuf.InvalidProtocolBufferException { - return newBuilder().mergeFrom(data).buildParsed(); - } - public static com.alibaba.rocketmq.common.protocol.MQProtos.QueueInfo parseFrom( - com.google.protobuf.ByteString data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return newBuilder().mergeFrom(data, extensionRegistry) - .buildParsed(); - } - public static com.alibaba.rocketmq.common.protocol.MQProtos.QueueInfo parseFrom(byte[] data) - throws com.google.protobuf.InvalidProtocolBufferException { - return newBuilder().mergeFrom(data).buildParsed(); - } - public static com.alibaba.rocketmq.common.protocol.MQProtos.QueueInfo parseFrom( - byte[] data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return newBuilder().mergeFrom(data, extensionRegistry) - .buildParsed(); - } - public static com.alibaba.rocketmq.common.protocol.MQProtos.QueueInfo parseFrom(java.io.InputStream input) - throws java.io.IOException { - return newBuilder().mergeFrom(input).buildParsed(); - } - public static com.alibaba.rocketmq.common.protocol.MQProtos.QueueInfo parseFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return newBuilder().mergeFrom(input, extensionRegistry) - .buildParsed(); - } - public static com.alibaba.rocketmq.common.protocol.MQProtos.QueueInfo parseDelimitedFrom(java.io.InputStream input) - throws java.io.IOException { - Builder builder = newBuilder(); - if (builder.mergeDelimitedFrom(input)) { - return builder.buildParsed(); - } else { - return null; - } - } - public static com.alibaba.rocketmq.common.protocol.MQProtos.QueueInfo parseDelimitedFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - Builder builder = newBuilder(); - if (builder.mergeDelimitedFrom(input, extensionRegistry)) { - return builder.buildParsed(); - } else { - return null; - } - } - public static com.alibaba.rocketmq.common.protocol.MQProtos.QueueInfo parseFrom( - com.google.protobuf.CodedInputStream input) - throws java.io.IOException { - return newBuilder().mergeFrom(input).buildParsed(); - } - public static com.alibaba.rocketmq.common.protocol.MQProtos.QueueInfo parseFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return newBuilder().mergeFrom(input, extensionRegistry) - .buildParsed(); - } - - public static Builder newBuilder() { return Builder.create(); } - public Builder newBuilderForType() { return newBuilder(); } - public static Builder newBuilder(com.alibaba.rocketmq.common.protocol.MQProtos.QueueInfo prototype) { - return newBuilder().mergeFrom(prototype); - } - public Builder toBuilder() { return newBuilder(this); } - - @java.lang.Override - protected Builder newBuilderForType( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - Builder builder = new Builder(parent); - return builder; - } - public static final class Builder extends - com.google.protobuf.GeneratedMessage.Builder - implements com.alibaba.rocketmq.common.protocol.MQProtos.QueueInfoOrBuilder { - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return com.alibaba.rocketmq.common.protocol.MQProtos.internal_static_rocketmq_QueueInfo_descriptor; - } - - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return com.alibaba.rocketmq.common.protocol.MQProtos.internal_static_rocketmq_QueueInfo_fieldAccessorTable; - } - - // Construct using com.alibaba.rocketmq.common.protocol.MQProtos.QueueInfo.newBuilder() - private Builder() { - maybeForceBuilderInitialization(); - } - - private Builder(BuilderParent parent) { - super(parent); - maybeForceBuilderInitialization(); - } - private void maybeForceBuilderInitialization() { - if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) { - } - } - private static Builder create() { - return new Builder(); - } - - public Builder clear() { - super.clear(); - brokerName_ = ""; - bitField0_ = (bitField0_ & ~0x00000001); - readQueueNums_ = 0; - bitField0_ = (bitField0_ & ~0x00000002); - writeQueueNums_ = 0; - bitField0_ = (bitField0_ & ~0x00000004); - perm_ = 0; - bitField0_ = (bitField0_ & ~0x00000008); - return this; - } - - public Builder clone() { - return create().mergeFrom(buildPartial()); - } - - public com.google.protobuf.Descriptors.Descriptor - getDescriptorForType() { - return com.alibaba.rocketmq.common.protocol.MQProtos.QueueInfo.getDescriptor(); - } - - public com.alibaba.rocketmq.common.protocol.MQProtos.QueueInfo getDefaultInstanceForType() { - return com.alibaba.rocketmq.common.protocol.MQProtos.QueueInfo.getDefaultInstance(); - } - - public com.alibaba.rocketmq.common.protocol.MQProtos.QueueInfo build() { - com.alibaba.rocketmq.common.protocol.MQProtos.QueueInfo result = buildPartial(); - if (!result.isInitialized()) { - throw newUninitializedMessageException(result); - } - return result; - } - - private com.alibaba.rocketmq.common.protocol.MQProtos.QueueInfo buildParsed() - throws com.google.protobuf.InvalidProtocolBufferException { - com.alibaba.rocketmq.common.protocol.MQProtos.QueueInfo result = buildPartial(); - if (!result.isInitialized()) { - throw newUninitializedMessageException( - result).asInvalidProtocolBufferException(); - } - return result; - } - - public com.alibaba.rocketmq.common.protocol.MQProtos.QueueInfo buildPartial() { - com.alibaba.rocketmq.common.protocol.MQProtos.QueueInfo result = new com.alibaba.rocketmq.common.protocol.MQProtos.QueueInfo(this); - int from_bitField0_ = bitField0_; - int to_bitField0_ = 0; - if (((from_bitField0_ & 0x00000001) == 0x00000001)) { - to_bitField0_ |= 0x00000001; - } - result.brokerName_ = brokerName_; - if (((from_bitField0_ & 0x00000002) == 0x00000002)) { - to_bitField0_ |= 0x00000002; - } - result.readQueueNums_ = readQueueNums_; - if (((from_bitField0_ & 0x00000004) == 0x00000004)) { - to_bitField0_ |= 0x00000004; - } - result.writeQueueNums_ = writeQueueNums_; - if (((from_bitField0_ & 0x00000008) == 0x00000008)) { - to_bitField0_ |= 0x00000008; - } - result.perm_ = perm_; - result.bitField0_ = to_bitField0_; - onBuilt(); - return result; - } - - public Builder mergeFrom(com.google.protobuf.Message other) { - if (other instanceof com.alibaba.rocketmq.common.protocol.MQProtos.QueueInfo) { - return mergeFrom((com.alibaba.rocketmq.common.protocol.MQProtos.QueueInfo)other); - } else { - super.mergeFrom(other); - return this; - } - } - - public Builder mergeFrom(com.alibaba.rocketmq.common.protocol.MQProtos.QueueInfo other) { - if (other == com.alibaba.rocketmq.common.protocol.MQProtos.QueueInfo.getDefaultInstance()) return this; - if (other.hasBrokerName()) { - setBrokerName(other.getBrokerName()); - } - if (other.hasReadQueueNums()) { - setReadQueueNums(other.getReadQueueNums()); - } - if (other.hasWriteQueueNums()) { - setWriteQueueNums(other.getWriteQueueNums()); - } - if (other.hasPerm()) { - setPerm(other.getPerm()); - } - this.mergeUnknownFields(other.getUnknownFields()); - return this; - } - - public final boolean isInitialized() { - if (!hasBrokerName()) { - - return false; - } - if (!hasReadQueueNums()) { - - return false; - } - if (!hasWriteQueueNums()) { - - return false; - } - if (!hasPerm()) { - - return false; - } - return true; - } - - public Builder mergeFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - com.google.protobuf.UnknownFieldSet.Builder unknownFields = - com.google.protobuf.UnknownFieldSet.newBuilder( - this.getUnknownFields()); - while (true) { - int tag = input.readTag(); - switch (tag) { - case 0: - this.setUnknownFields(unknownFields.build()); - onChanged(); - return this; - default: { - if (!parseUnknownField(input, unknownFields, - extensionRegistry, tag)) { - this.setUnknownFields(unknownFields.build()); - onChanged(); - return this; - } - break; - } - case 10: { - bitField0_ |= 0x00000001; - brokerName_ = input.readBytes(); - break; - } - case 16: { - bitField0_ |= 0x00000002; - readQueueNums_ = input.readInt32(); - break; - } - case 24: { - bitField0_ |= 0x00000004; - writeQueueNums_ = input.readInt32(); - break; - } - case 32: { - bitField0_ |= 0x00000008; - perm_ = input.readInt32(); - break; - } - } - } - } - - private int bitField0_; - - // required string brokerName = 1; - private java.lang.Object brokerName_ = ""; - public boolean hasBrokerName() { - return ((bitField0_ & 0x00000001) == 0x00000001); - } - public String getBrokerName() { - java.lang.Object ref = brokerName_; - if (!(ref instanceof String)) { - String s = ((com.google.protobuf.ByteString) ref).toStringUtf8(); - brokerName_ = s; - return s; - } else { - return (String) ref; - } - } - public Builder setBrokerName(String value) { - if (value == null) { - throw new NullPointerException(); - } - bitField0_ |= 0x00000001; - brokerName_ = value; - onChanged(); - return this; - } - public Builder clearBrokerName() { - bitField0_ = (bitField0_ & ~0x00000001); - brokerName_ = getDefaultInstance().getBrokerName(); - onChanged(); - return this; - } - void setBrokerName(com.google.protobuf.ByteString value) { - bitField0_ |= 0x00000001; - brokerName_ = value; - onChanged(); - } - - // required int32 readQueueNums = 2; - private int readQueueNums_ ; - public boolean hasReadQueueNums() { - return ((bitField0_ & 0x00000002) == 0x00000002); - } - public int getReadQueueNums() { - return readQueueNums_; - } - public Builder setReadQueueNums(int value) { - bitField0_ |= 0x00000002; - readQueueNums_ = value; - onChanged(); - return this; - } - public Builder clearReadQueueNums() { - bitField0_ = (bitField0_ & ~0x00000002); - readQueueNums_ = 0; - onChanged(); - return this; - } - - // required int32 writeQueueNums = 3; - private int writeQueueNums_ ; - public boolean hasWriteQueueNums() { - return ((bitField0_ & 0x00000004) == 0x00000004); - } - public int getWriteQueueNums() { - return writeQueueNums_; - } - public Builder setWriteQueueNums(int value) { - bitField0_ |= 0x00000004; - writeQueueNums_ = value; - onChanged(); - return this; - } - public Builder clearWriteQueueNums() { - bitField0_ = (bitField0_ & ~0x00000004); - writeQueueNums_ = 0; - onChanged(); - return this; - } - - // required int32 perm = 4; - private int perm_ ; - public boolean hasPerm() { - return ((bitField0_ & 0x00000008) == 0x00000008); - } - public int getPerm() { - return perm_; - } - public Builder setPerm(int value) { - bitField0_ |= 0x00000008; - perm_ = value; - onChanged(); - return this; - } - public Builder clearPerm() { - bitField0_ = (bitField0_ & ~0x00000008); - perm_ = 0; - onChanged(); - return this; - } - - // @@protoc_insertion_point(builder_scope:rocketmq.QueueInfo) - } - - static { - defaultInstance = new QueueInfo(true); - defaultInstance.initFields(); - } - - // @@protoc_insertion_point(class_scope:rocketmq.QueueInfo) - } - - public interface TopicRouteInfoOrBuilder - extends com.google.protobuf.MessageOrBuilder { - - // repeated .rocketmq.QueueInfo queueInfos = 1; - java.util.List - getQueueInfosList(); - com.alibaba.rocketmq.common.protocol.MQProtos.QueueInfo getQueueInfos(int index); - int getQueueInfosCount(); - java.util.List - getQueueInfosOrBuilderList(); - com.alibaba.rocketmq.common.protocol.MQProtos.QueueInfoOrBuilder getQueueInfosOrBuilder( - int index); - - // repeated .rocketmq.BrokerInfo brokerInfos = 2; - java.util.List - getBrokerInfosList(); - com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo getBrokerInfos(int index); - int getBrokerInfosCount(); - java.util.List - getBrokerInfosOrBuilderList(); - com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfoOrBuilder getBrokerInfosOrBuilder( - int index); - - // optional string orderTopicConf = 3; - boolean hasOrderTopicConf(); - String getOrderTopicConf(); - } - public static final class TopicRouteInfo extends - com.google.protobuf.GeneratedMessage - implements TopicRouteInfoOrBuilder { - // Use TopicRouteInfo.newBuilder() to construct. - private TopicRouteInfo(Builder builder) { - super(builder); - } - private TopicRouteInfo(boolean noInit) {} - - private static final TopicRouteInfo defaultInstance; - public static TopicRouteInfo getDefaultInstance() { - return defaultInstance; - } - - public TopicRouteInfo getDefaultInstanceForType() { - return defaultInstance; - } - - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return com.alibaba.rocketmq.common.protocol.MQProtos.internal_static_rocketmq_TopicRouteInfo_descriptor; - } - - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return com.alibaba.rocketmq.common.protocol.MQProtos.internal_static_rocketmq_TopicRouteInfo_fieldAccessorTable; - } - - private int bitField0_; - // repeated .rocketmq.QueueInfo queueInfos = 1; - public static final int QUEUEINFOS_FIELD_NUMBER = 1; - private java.util.List queueInfos_; - public java.util.List getQueueInfosList() { - return queueInfos_; - } - public java.util.List - getQueueInfosOrBuilderList() { - return queueInfos_; - } - public int getQueueInfosCount() { - return queueInfos_.size(); - } - public com.alibaba.rocketmq.common.protocol.MQProtos.QueueInfo getQueueInfos(int index) { - return queueInfos_.get(index); - } - public com.alibaba.rocketmq.common.protocol.MQProtos.QueueInfoOrBuilder getQueueInfosOrBuilder( - int index) { - return queueInfos_.get(index); - } - - // repeated .rocketmq.BrokerInfo brokerInfos = 2; - public static final int BROKERINFOS_FIELD_NUMBER = 2; - private java.util.List brokerInfos_; - public java.util.List getBrokerInfosList() { - return brokerInfos_; - } - public java.util.List - getBrokerInfosOrBuilderList() { - return brokerInfos_; - } - public int getBrokerInfosCount() { - return brokerInfos_.size(); - } - public com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo getBrokerInfos(int index) { - return brokerInfos_.get(index); - } - public com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfoOrBuilder getBrokerInfosOrBuilder( - int index) { - return brokerInfos_.get(index); - } - - // optional string orderTopicConf = 3; - public static final int ORDERTOPICCONF_FIELD_NUMBER = 3; - private java.lang.Object orderTopicConf_; - public boolean hasOrderTopicConf() { - return ((bitField0_ & 0x00000001) == 0x00000001); - } - public String getOrderTopicConf() { - java.lang.Object ref = orderTopicConf_; - if (ref instanceof String) { - return (String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - String s = bs.toStringUtf8(); - if (com.google.protobuf.Internal.isValidUtf8(bs)) { - orderTopicConf_ = s; - } - return s; - } - } - private com.google.protobuf.ByteString getOrderTopicConfBytes() { - java.lang.Object ref = orderTopicConf_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8((String) ref); - orderTopicConf_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - private void initFields() { - queueInfos_ = java.util.Collections.emptyList(); - brokerInfos_ = java.util.Collections.emptyList(); - orderTopicConf_ = ""; - } - private byte memoizedIsInitialized = -1; - public final boolean isInitialized() { - byte isInitialized = memoizedIsInitialized; - if (isInitialized != -1) return isInitialized == 1; - - for (int i = 0; i < getQueueInfosCount(); i++) { - if (!getQueueInfos(i).isInitialized()) { - memoizedIsInitialized = 0; - return false; - } - } - for (int i = 0; i < getBrokerInfosCount(); i++) { - if (!getBrokerInfos(i).isInitialized()) { - memoizedIsInitialized = 0; - return false; - } - } - memoizedIsInitialized = 1; - return true; - } - - public void writeTo(com.google.protobuf.CodedOutputStream output) - throws java.io.IOException { - getSerializedSize(); - for (int i = 0; i < queueInfos_.size(); i++) { - output.writeMessage(1, queueInfos_.get(i)); - } - for (int i = 0; i < brokerInfos_.size(); i++) { - output.writeMessage(2, brokerInfos_.get(i)); - } - if (((bitField0_ & 0x00000001) == 0x00000001)) { - output.writeBytes(3, getOrderTopicConfBytes()); - } - getUnknownFields().writeTo(output); - } - - private int memoizedSerializedSize = -1; - public int getSerializedSize() { - int size = memoizedSerializedSize; - if (size != -1) return size; - - size = 0; - for (int i = 0; i < queueInfos_.size(); i++) { - size += com.google.protobuf.CodedOutputStream - .computeMessageSize(1, queueInfos_.get(i)); - } - for (int i = 0; i < brokerInfos_.size(); i++) { - size += com.google.protobuf.CodedOutputStream - .computeMessageSize(2, brokerInfos_.get(i)); - } - if (((bitField0_ & 0x00000001) == 0x00000001)) { - size += com.google.protobuf.CodedOutputStream - .computeBytesSize(3, getOrderTopicConfBytes()); - } - size += getUnknownFields().getSerializedSize(); - memoizedSerializedSize = size; - return size; - } - - private static final long serialVersionUID = 0L; - @java.lang.Override - protected java.lang.Object writeReplace() - throws java.io.ObjectStreamException { - return super.writeReplace(); - } - - public static com.alibaba.rocketmq.common.protocol.MQProtos.TopicRouteInfo parseFrom( - com.google.protobuf.ByteString data) - throws com.google.protobuf.InvalidProtocolBufferException { - return newBuilder().mergeFrom(data).buildParsed(); - } - public static com.alibaba.rocketmq.common.protocol.MQProtos.TopicRouteInfo parseFrom( - com.google.protobuf.ByteString data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return newBuilder().mergeFrom(data, extensionRegistry) - .buildParsed(); - } - public static com.alibaba.rocketmq.common.protocol.MQProtos.TopicRouteInfo parseFrom(byte[] data) - throws com.google.protobuf.InvalidProtocolBufferException { - return newBuilder().mergeFrom(data).buildParsed(); - } - public static com.alibaba.rocketmq.common.protocol.MQProtos.TopicRouteInfo parseFrom( - byte[] data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return newBuilder().mergeFrom(data, extensionRegistry) - .buildParsed(); - } - public static com.alibaba.rocketmq.common.protocol.MQProtos.TopicRouteInfo parseFrom(java.io.InputStream input) - throws java.io.IOException { - return newBuilder().mergeFrom(input).buildParsed(); - } - public static com.alibaba.rocketmq.common.protocol.MQProtos.TopicRouteInfo parseFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return newBuilder().mergeFrom(input, extensionRegistry) - .buildParsed(); - } - public static com.alibaba.rocketmq.common.protocol.MQProtos.TopicRouteInfo parseDelimitedFrom(java.io.InputStream input) - throws java.io.IOException { - Builder builder = newBuilder(); - if (builder.mergeDelimitedFrom(input)) { - return builder.buildParsed(); - } else { - return null; - } - } - public static com.alibaba.rocketmq.common.protocol.MQProtos.TopicRouteInfo parseDelimitedFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - Builder builder = newBuilder(); - if (builder.mergeDelimitedFrom(input, extensionRegistry)) { - return builder.buildParsed(); - } else { - return null; - } - } - public static com.alibaba.rocketmq.common.protocol.MQProtos.TopicRouteInfo parseFrom( - com.google.protobuf.CodedInputStream input) - throws java.io.IOException { - return newBuilder().mergeFrom(input).buildParsed(); - } - public static com.alibaba.rocketmq.common.protocol.MQProtos.TopicRouteInfo parseFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return newBuilder().mergeFrom(input, extensionRegistry) - .buildParsed(); - } - - public static Builder newBuilder() { return Builder.create(); } - public Builder newBuilderForType() { return newBuilder(); } - public static Builder newBuilder(com.alibaba.rocketmq.common.protocol.MQProtos.TopicRouteInfo prototype) { - return newBuilder().mergeFrom(prototype); - } - public Builder toBuilder() { return newBuilder(this); } - - @java.lang.Override - protected Builder newBuilderForType( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - Builder builder = new Builder(parent); - return builder; - } - public static final class Builder extends - com.google.protobuf.GeneratedMessage.Builder - implements com.alibaba.rocketmq.common.protocol.MQProtos.TopicRouteInfoOrBuilder { - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return com.alibaba.rocketmq.common.protocol.MQProtos.internal_static_rocketmq_TopicRouteInfo_descriptor; - } - - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return com.alibaba.rocketmq.common.protocol.MQProtos.internal_static_rocketmq_TopicRouteInfo_fieldAccessorTable; - } - - // Construct using com.alibaba.rocketmq.common.protocol.MQProtos.TopicRouteInfo.newBuilder() - private Builder() { - maybeForceBuilderInitialization(); - } - - private Builder(BuilderParent parent) { - super(parent); - maybeForceBuilderInitialization(); - } - private void maybeForceBuilderInitialization() { - if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) { - getQueueInfosFieldBuilder(); - getBrokerInfosFieldBuilder(); - } - } - private static Builder create() { - return new Builder(); - } - - public Builder clear() { - super.clear(); - if (queueInfosBuilder_ == null) { - queueInfos_ = java.util.Collections.emptyList(); - bitField0_ = (bitField0_ & ~0x00000001); - } else { - queueInfosBuilder_.clear(); - } - if (brokerInfosBuilder_ == null) { - brokerInfos_ = java.util.Collections.emptyList(); - bitField0_ = (bitField0_ & ~0x00000002); - } else { - brokerInfosBuilder_.clear(); - } - orderTopicConf_ = ""; - bitField0_ = (bitField0_ & ~0x00000004); - return this; - } - - public Builder clone() { - return create().mergeFrom(buildPartial()); - } - - public com.google.protobuf.Descriptors.Descriptor - getDescriptorForType() { - return com.alibaba.rocketmq.common.protocol.MQProtos.TopicRouteInfo.getDescriptor(); - } - - public com.alibaba.rocketmq.common.protocol.MQProtos.TopicRouteInfo getDefaultInstanceForType() { - return com.alibaba.rocketmq.common.protocol.MQProtos.TopicRouteInfo.getDefaultInstance(); - } - - public com.alibaba.rocketmq.common.protocol.MQProtos.TopicRouteInfo build() { - com.alibaba.rocketmq.common.protocol.MQProtos.TopicRouteInfo result = buildPartial(); - if (!result.isInitialized()) { - throw newUninitializedMessageException(result); - } - return result; - } - - private com.alibaba.rocketmq.common.protocol.MQProtos.TopicRouteInfo buildParsed() - throws com.google.protobuf.InvalidProtocolBufferException { - com.alibaba.rocketmq.common.protocol.MQProtos.TopicRouteInfo result = buildPartial(); - if (!result.isInitialized()) { - throw newUninitializedMessageException( - result).asInvalidProtocolBufferException(); - } - return result; - } - - public com.alibaba.rocketmq.common.protocol.MQProtos.TopicRouteInfo buildPartial() { - com.alibaba.rocketmq.common.protocol.MQProtos.TopicRouteInfo result = new com.alibaba.rocketmq.common.protocol.MQProtos.TopicRouteInfo(this); - int from_bitField0_ = bitField0_; - int to_bitField0_ = 0; - if (queueInfosBuilder_ == null) { - if (((bitField0_ & 0x00000001) == 0x00000001)) { - queueInfos_ = java.util.Collections.unmodifiableList(queueInfos_); - bitField0_ = (bitField0_ & ~0x00000001); - } - result.queueInfos_ = queueInfos_; - } else { - result.queueInfos_ = queueInfosBuilder_.build(); - } - if (brokerInfosBuilder_ == null) { - if (((bitField0_ & 0x00000002) == 0x00000002)) { - brokerInfos_ = java.util.Collections.unmodifiableList(brokerInfos_); - bitField0_ = (bitField0_ & ~0x00000002); - } - result.brokerInfos_ = brokerInfos_; - } else { - result.brokerInfos_ = brokerInfosBuilder_.build(); - } - if (((from_bitField0_ & 0x00000004) == 0x00000004)) { - to_bitField0_ |= 0x00000001; - } - result.orderTopicConf_ = orderTopicConf_; - result.bitField0_ = to_bitField0_; - onBuilt(); - return result; - } - - public Builder mergeFrom(com.google.protobuf.Message other) { - if (other instanceof com.alibaba.rocketmq.common.protocol.MQProtos.TopicRouteInfo) { - return mergeFrom((com.alibaba.rocketmq.common.protocol.MQProtos.TopicRouteInfo)other); - } else { - super.mergeFrom(other); - return this; - } - } - - public Builder mergeFrom(com.alibaba.rocketmq.common.protocol.MQProtos.TopicRouteInfo other) { - if (other == com.alibaba.rocketmq.common.protocol.MQProtos.TopicRouteInfo.getDefaultInstance()) return this; - if (queueInfosBuilder_ == null) { - if (!other.queueInfos_.isEmpty()) { - if (queueInfos_.isEmpty()) { - queueInfos_ = other.queueInfos_; - bitField0_ = (bitField0_ & ~0x00000001); - } else { - ensureQueueInfosIsMutable(); - queueInfos_.addAll(other.queueInfos_); - } - onChanged(); - } - } else { - if (!other.queueInfos_.isEmpty()) { - if (queueInfosBuilder_.isEmpty()) { - queueInfosBuilder_.dispose(); - queueInfosBuilder_ = null; - queueInfos_ = other.queueInfos_; - bitField0_ = (bitField0_ & ~0x00000001); - queueInfosBuilder_ = - com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders ? - getQueueInfosFieldBuilder() : null; - } else { - queueInfosBuilder_.addAllMessages(other.queueInfos_); - } - } - } - if (brokerInfosBuilder_ == null) { - if (!other.brokerInfos_.isEmpty()) { - if (brokerInfos_.isEmpty()) { - brokerInfos_ = other.brokerInfos_; - bitField0_ = (bitField0_ & ~0x00000002); - } else { - ensureBrokerInfosIsMutable(); - brokerInfos_.addAll(other.brokerInfos_); - } - onChanged(); - } - } else { - if (!other.brokerInfos_.isEmpty()) { - if (brokerInfosBuilder_.isEmpty()) { - brokerInfosBuilder_.dispose(); - brokerInfosBuilder_ = null; - brokerInfos_ = other.brokerInfos_; - bitField0_ = (bitField0_ & ~0x00000002); - brokerInfosBuilder_ = - com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders ? - getBrokerInfosFieldBuilder() : null; - } else { - brokerInfosBuilder_.addAllMessages(other.brokerInfos_); - } - } - } - if (other.hasOrderTopicConf()) { - setOrderTopicConf(other.getOrderTopicConf()); - } - this.mergeUnknownFields(other.getUnknownFields()); - return this; - } - - public final boolean isInitialized() { - for (int i = 0; i < getQueueInfosCount(); i++) { - if (!getQueueInfos(i).isInitialized()) { - - return false; - } - } - for (int i = 0; i < getBrokerInfosCount(); i++) { - if (!getBrokerInfos(i).isInitialized()) { - - return false; - } - } - return true; - } - - public Builder mergeFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - com.google.protobuf.UnknownFieldSet.Builder unknownFields = - com.google.protobuf.UnknownFieldSet.newBuilder( - this.getUnknownFields()); - while (true) { - int tag = input.readTag(); - switch (tag) { - case 0: - this.setUnknownFields(unknownFields.build()); - onChanged(); - return this; - default: { - if (!parseUnknownField(input, unknownFields, - extensionRegistry, tag)) { - this.setUnknownFields(unknownFields.build()); - onChanged(); - return this; - } - break; - } - case 10: { - com.alibaba.rocketmq.common.protocol.MQProtos.QueueInfo.Builder subBuilder = com.alibaba.rocketmq.common.protocol.MQProtos.QueueInfo.newBuilder(); - input.readMessage(subBuilder, extensionRegistry); - addQueueInfos(subBuilder.buildPartial()); - break; - } - case 18: { - com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo.Builder subBuilder = com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo.newBuilder(); - input.readMessage(subBuilder, extensionRegistry); - addBrokerInfos(subBuilder.buildPartial()); - break; - } - case 26: { - bitField0_ |= 0x00000004; - orderTopicConf_ = input.readBytes(); - break; - } - } - } - } - - private int bitField0_; - - // repeated .rocketmq.QueueInfo queueInfos = 1; - private java.util.List queueInfos_ = - java.util.Collections.emptyList(); - private void ensureQueueInfosIsMutable() { - if (!((bitField0_ & 0x00000001) == 0x00000001)) { - queueInfos_ = new java.util.ArrayList(queueInfos_); - bitField0_ |= 0x00000001; - } - } - - private com.google.protobuf.RepeatedFieldBuilder< - com.alibaba.rocketmq.common.protocol.MQProtos.QueueInfo, com.alibaba.rocketmq.common.protocol.MQProtos.QueueInfo.Builder, com.alibaba.rocketmq.common.protocol.MQProtos.QueueInfoOrBuilder> queueInfosBuilder_; - - public java.util.List getQueueInfosList() { - if (queueInfosBuilder_ == null) { - return java.util.Collections.unmodifiableList(queueInfos_); - } else { - return queueInfosBuilder_.getMessageList(); - } - } - public int getQueueInfosCount() { - if (queueInfosBuilder_ == null) { - return queueInfos_.size(); - } else { - return queueInfosBuilder_.getCount(); - } - } - public com.alibaba.rocketmq.common.protocol.MQProtos.QueueInfo getQueueInfos(int index) { - if (queueInfosBuilder_ == null) { - return queueInfos_.get(index); - } else { - return queueInfosBuilder_.getMessage(index); - } - } - public Builder setQueueInfos( - int index, com.alibaba.rocketmq.common.protocol.MQProtos.QueueInfo value) { - if (queueInfosBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - ensureQueueInfosIsMutable(); - queueInfos_.set(index, value); - onChanged(); - } else { - queueInfosBuilder_.setMessage(index, value); - } - return this; - } - public Builder setQueueInfos( - int index, com.alibaba.rocketmq.common.protocol.MQProtos.QueueInfo.Builder builderForValue) { - if (queueInfosBuilder_ == null) { - ensureQueueInfosIsMutable(); - queueInfos_.set(index, builderForValue.build()); - onChanged(); - } else { - queueInfosBuilder_.setMessage(index, builderForValue.build()); - } - return this; - } - public Builder addQueueInfos(com.alibaba.rocketmq.common.protocol.MQProtos.QueueInfo value) { - if (queueInfosBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - ensureQueueInfosIsMutable(); - queueInfos_.add(value); - onChanged(); - } else { - queueInfosBuilder_.addMessage(value); - } - return this; - } - public Builder addQueueInfos( - int index, com.alibaba.rocketmq.common.protocol.MQProtos.QueueInfo value) { - if (queueInfosBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - ensureQueueInfosIsMutable(); - queueInfos_.add(index, value); - onChanged(); - } else { - queueInfosBuilder_.addMessage(index, value); - } - return this; - } - public Builder addQueueInfos( - com.alibaba.rocketmq.common.protocol.MQProtos.QueueInfo.Builder builderForValue) { - if (queueInfosBuilder_ == null) { - ensureQueueInfosIsMutable(); - queueInfos_.add(builderForValue.build()); - onChanged(); - } else { - queueInfosBuilder_.addMessage(builderForValue.build()); - } - return this; - } - public Builder addQueueInfos( - int index, com.alibaba.rocketmq.common.protocol.MQProtos.QueueInfo.Builder builderForValue) { - if (queueInfosBuilder_ == null) { - ensureQueueInfosIsMutable(); - queueInfos_.add(index, builderForValue.build()); - onChanged(); - } else { - queueInfosBuilder_.addMessage(index, builderForValue.build()); - } - return this; - } - public Builder addAllQueueInfos( - java.lang.Iterable values) { - if (queueInfosBuilder_ == null) { - ensureQueueInfosIsMutable(); - super.addAll(values, queueInfos_); - onChanged(); - } else { - queueInfosBuilder_.addAllMessages(values); - } - return this; - } - public Builder clearQueueInfos() { - if (queueInfosBuilder_ == null) { - queueInfos_ = java.util.Collections.emptyList(); - bitField0_ = (bitField0_ & ~0x00000001); - onChanged(); - } else { - queueInfosBuilder_.clear(); - } - return this; - } - public Builder removeQueueInfos(int index) { - if (queueInfosBuilder_ == null) { - ensureQueueInfosIsMutable(); - queueInfos_.remove(index); - onChanged(); - } else { - queueInfosBuilder_.remove(index); - } - return this; - } - public com.alibaba.rocketmq.common.protocol.MQProtos.QueueInfo.Builder getQueueInfosBuilder( - int index) { - return getQueueInfosFieldBuilder().getBuilder(index); - } - public com.alibaba.rocketmq.common.protocol.MQProtos.QueueInfoOrBuilder getQueueInfosOrBuilder( - int index) { - if (queueInfosBuilder_ == null) { - return queueInfos_.get(index); } else { - return queueInfosBuilder_.getMessageOrBuilder(index); - } - } - public java.util.List - getQueueInfosOrBuilderList() { - if (queueInfosBuilder_ != null) { - return queueInfosBuilder_.getMessageOrBuilderList(); - } else { - return java.util.Collections.unmodifiableList(queueInfos_); - } - } - public com.alibaba.rocketmq.common.protocol.MQProtos.QueueInfo.Builder addQueueInfosBuilder() { - return getQueueInfosFieldBuilder().addBuilder( - com.alibaba.rocketmq.common.protocol.MQProtos.QueueInfo.getDefaultInstance()); - } - public com.alibaba.rocketmq.common.protocol.MQProtos.QueueInfo.Builder addQueueInfosBuilder( - int index) { - return getQueueInfosFieldBuilder().addBuilder( - index, com.alibaba.rocketmq.common.protocol.MQProtos.QueueInfo.getDefaultInstance()); - } - public java.util.List - getQueueInfosBuilderList() { - return getQueueInfosFieldBuilder().getBuilderList(); - } - private com.google.protobuf.RepeatedFieldBuilder< - com.alibaba.rocketmq.common.protocol.MQProtos.QueueInfo, com.alibaba.rocketmq.common.protocol.MQProtos.QueueInfo.Builder, com.alibaba.rocketmq.common.protocol.MQProtos.QueueInfoOrBuilder> - getQueueInfosFieldBuilder() { - if (queueInfosBuilder_ == null) { - queueInfosBuilder_ = new com.google.protobuf.RepeatedFieldBuilder< - com.alibaba.rocketmq.common.protocol.MQProtos.QueueInfo, com.alibaba.rocketmq.common.protocol.MQProtos.QueueInfo.Builder, com.alibaba.rocketmq.common.protocol.MQProtos.QueueInfoOrBuilder>( - queueInfos_, - ((bitField0_ & 0x00000001) == 0x00000001), - getParentForChildren(), - isClean()); - queueInfos_ = null; - } - return queueInfosBuilder_; - } - - // repeated .rocketmq.BrokerInfo brokerInfos = 2; - private java.util.List brokerInfos_ = - java.util.Collections.emptyList(); - private void ensureBrokerInfosIsMutable() { - if (!((bitField0_ & 0x00000002) == 0x00000002)) { - brokerInfos_ = new java.util.ArrayList(brokerInfos_); - bitField0_ |= 0x00000002; - } - } - - private com.google.protobuf.RepeatedFieldBuilder< - com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo, com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo.Builder, com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfoOrBuilder> brokerInfosBuilder_; - - public java.util.List getBrokerInfosList() { - if (brokerInfosBuilder_ == null) { - return java.util.Collections.unmodifiableList(brokerInfos_); - } else { - return brokerInfosBuilder_.getMessageList(); - } - } - public int getBrokerInfosCount() { - if (brokerInfosBuilder_ == null) { - return brokerInfos_.size(); - } else { - return brokerInfosBuilder_.getCount(); - } - } - public com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo getBrokerInfos(int index) { - if (brokerInfosBuilder_ == null) { - return brokerInfos_.get(index); - } else { - return brokerInfosBuilder_.getMessage(index); - } - } - public Builder setBrokerInfos( - int index, com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo value) { - if (brokerInfosBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - ensureBrokerInfosIsMutable(); - brokerInfos_.set(index, value); - onChanged(); - } else { - brokerInfosBuilder_.setMessage(index, value); - } - return this; - } - public Builder setBrokerInfos( - int index, com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo.Builder builderForValue) { - if (brokerInfosBuilder_ == null) { - ensureBrokerInfosIsMutable(); - brokerInfos_.set(index, builderForValue.build()); - onChanged(); - } else { - brokerInfosBuilder_.setMessage(index, builderForValue.build()); - } - return this; - } - public Builder addBrokerInfos(com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo value) { - if (brokerInfosBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - ensureBrokerInfosIsMutable(); - brokerInfos_.add(value); - onChanged(); - } else { - brokerInfosBuilder_.addMessage(value); - } - return this; - } - public Builder addBrokerInfos( - int index, com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo value) { - if (brokerInfosBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - ensureBrokerInfosIsMutable(); - brokerInfos_.add(index, value); - onChanged(); - } else { - brokerInfosBuilder_.addMessage(index, value); - } - return this; - } - public Builder addBrokerInfos( - com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo.Builder builderForValue) { - if (brokerInfosBuilder_ == null) { - ensureBrokerInfosIsMutable(); - brokerInfos_.add(builderForValue.build()); - onChanged(); - } else { - brokerInfosBuilder_.addMessage(builderForValue.build()); - } - return this; - } - public Builder addBrokerInfos( - int index, com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo.Builder builderForValue) { - if (brokerInfosBuilder_ == null) { - ensureBrokerInfosIsMutable(); - brokerInfos_.add(index, builderForValue.build()); - onChanged(); - } else { - brokerInfosBuilder_.addMessage(index, builderForValue.build()); - } - return this; - } - public Builder addAllBrokerInfos( - java.lang.Iterable values) { - if (brokerInfosBuilder_ == null) { - ensureBrokerInfosIsMutable(); - super.addAll(values, brokerInfos_); - onChanged(); - } else { - brokerInfosBuilder_.addAllMessages(values); - } - return this; - } - public Builder clearBrokerInfos() { - if (brokerInfosBuilder_ == null) { - brokerInfos_ = java.util.Collections.emptyList(); - bitField0_ = (bitField0_ & ~0x00000002); - onChanged(); - } else { - brokerInfosBuilder_.clear(); - } - return this; - } - public Builder removeBrokerInfos(int index) { - if (brokerInfosBuilder_ == null) { - ensureBrokerInfosIsMutable(); - brokerInfos_.remove(index); - onChanged(); - } else { - brokerInfosBuilder_.remove(index); - } - return this; - } - public com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo.Builder getBrokerInfosBuilder( - int index) { - return getBrokerInfosFieldBuilder().getBuilder(index); - } - public com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfoOrBuilder getBrokerInfosOrBuilder( - int index) { - if (brokerInfosBuilder_ == null) { - return brokerInfos_.get(index); } else { - return brokerInfosBuilder_.getMessageOrBuilder(index); - } - } - public java.util.List - getBrokerInfosOrBuilderList() { - if (brokerInfosBuilder_ != null) { - return brokerInfosBuilder_.getMessageOrBuilderList(); - } else { - return java.util.Collections.unmodifiableList(brokerInfos_); - } - } - public com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo.Builder addBrokerInfosBuilder() { - return getBrokerInfosFieldBuilder().addBuilder( - com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo.getDefaultInstance()); - } - public com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo.Builder addBrokerInfosBuilder( - int index) { - return getBrokerInfosFieldBuilder().addBuilder( - index, com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo.getDefaultInstance()); - } - public java.util.List - getBrokerInfosBuilderList() { - return getBrokerInfosFieldBuilder().getBuilderList(); - } - private com.google.protobuf.RepeatedFieldBuilder< - com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo, com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo.Builder, com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfoOrBuilder> - getBrokerInfosFieldBuilder() { - if (brokerInfosBuilder_ == null) { - brokerInfosBuilder_ = new com.google.protobuf.RepeatedFieldBuilder< - com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo, com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo.Builder, com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfoOrBuilder>( - brokerInfos_, - ((bitField0_ & 0x00000002) == 0x00000002), - getParentForChildren(), - isClean()); - brokerInfos_ = null; - } - return brokerInfosBuilder_; - } - - // optional string orderTopicConf = 3; - private java.lang.Object orderTopicConf_ = ""; - public boolean hasOrderTopicConf() { - return ((bitField0_ & 0x00000004) == 0x00000004); - } - public String getOrderTopicConf() { - java.lang.Object ref = orderTopicConf_; - if (!(ref instanceof String)) { - String s = ((com.google.protobuf.ByteString) ref).toStringUtf8(); - orderTopicConf_ = s; - return s; - } else { - return (String) ref; - } - } - public Builder setOrderTopicConf(String value) { - if (value == null) { - throw new NullPointerException(); - } - bitField0_ |= 0x00000004; - orderTopicConf_ = value; - onChanged(); - return this; - } - public Builder clearOrderTopicConf() { - bitField0_ = (bitField0_ & ~0x00000004); - orderTopicConf_ = getDefaultInstance().getOrderTopicConf(); - onChanged(); - return this; - } - void setOrderTopicConf(com.google.protobuf.ByteString value) { - bitField0_ |= 0x00000004; - orderTopicConf_ = value; - onChanged(); - } - - // @@protoc_insertion_point(builder_scope:rocketmq.TopicRouteInfo) - } - - static { - defaultInstance = new TopicRouteInfo(true); - defaultInstance.initFields(); - } - - // @@protoc_insertion_point(class_scope:rocketmq.TopicRouteInfo) - } - - public interface ProducerInfoOrBuilder - extends com.google.protobuf.MessageOrBuilder { - - // required string groupName = 1; - boolean hasGroupName(); - String getGroupName(); - } - public static final class ProducerInfo extends - com.google.protobuf.GeneratedMessage - implements ProducerInfoOrBuilder { - // Use ProducerInfo.newBuilder() to construct. - private ProducerInfo(Builder builder) { - super(builder); - } - private ProducerInfo(boolean noInit) {} - - private static final ProducerInfo defaultInstance; - public static ProducerInfo getDefaultInstance() { - return defaultInstance; - } - - public ProducerInfo getDefaultInstanceForType() { - return defaultInstance; - } - - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return com.alibaba.rocketmq.common.protocol.MQProtos.internal_static_rocketmq_ProducerInfo_descriptor; - } - - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return com.alibaba.rocketmq.common.protocol.MQProtos.internal_static_rocketmq_ProducerInfo_fieldAccessorTable; - } - - private int bitField0_; - // required string groupName = 1; - public static final int GROUPNAME_FIELD_NUMBER = 1; - private java.lang.Object groupName_; - public boolean hasGroupName() { - return ((bitField0_ & 0x00000001) == 0x00000001); - } - public String getGroupName() { - java.lang.Object ref = groupName_; - if (ref instanceof String) { - return (String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - String s = bs.toStringUtf8(); - if (com.google.protobuf.Internal.isValidUtf8(bs)) { - groupName_ = s; - } - return s; - } - } - private com.google.protobuf.ByteString getGroupNameBytes() { - java.lang.Object ref = groupName_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8((String) ref); - groupName_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - private void initFields() { - groupName_ = ""; - } - private byte memoizedIsInitialized = -1; - public final boolean isInitialized() { - byte isInitialized = memoizedIsInitialized; - if (isInitialized != -1) return isInitialized == 1; - - if (!hasGroupName()) { - memoizedIsInitialized = 0; - return false; - } - memoizedIsInitialized = 1; - return true; - } - - public void writeTo(com.google.protobuf.CodedOutputStream output) - throws java.io.IOException { - getSerializedSize(); - if (((bitField0_ & 0x00000001) == 0x00000001)) { - output.writeBytes(1, getGroupNameBytes()); - } - getUnknownFields().writeTo(output); - } - - private int memoizedSerializedSize = -1; - public int getSerializedSize() { - int size = memoizedSerializedSize; - if (size != -1) return size; - - size = 0; - if (((bitField0_ & 0x00000001) == 0x00000001)) { - size += com.google.protobuf.CodedOutputStream - .computeBytesSize(1, getGroupNameBytes()); - } - size += getUnknownFields().getSerializedSize(); - memoizedSerializedSize = size; - return size; - } - - private static final long serialVersionUID = 0L; - @java.lang.Override - protected java.lang.Object writeReplace() - throws java.io.ObjectStreamException { - return super.writeReplace(); - } - - public static com.alibaba.rocketmq.common.protocol.MQProtos.ProducerInfo parseFrom( - com.google.protobuf.ByteString data) - throws com.google.protobuf.InvalidProtocolBufferException { - return newBuilder().mergeFrom(data).buildParsed(); - } - public static com.alibaba.rocketmq.common.protocol.MQProtos.ProducerInfo parseFrom( - com.google.protobuf.ByteString data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return newBuilder().mergeFrom(data, extensionRegistry) - .buildParsed(); - } - public static com.alibaba.rocketmq.common.protocol.MQProtos.ProducerInfo parseFrom(byte[] data) - throws com.google.protobuf.InvalidProtocolBufferException { - return newBuilder().mergeFrom(data).buildParsed(); - } - public static com.alibaba.rocketmq.common.protocol.MQProtos.ProducerInfo parseFrom( - byte[] data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return newBuilder().mergeFrom(data, extensionRegistry) - .buildParsed(); - } - public static com.alibaba.rocketmq.common.protocol.MQProtos.ProducerInfo parseFrom(java.io.InputStream input) - throws java.io.IOException { - return newBuilder().mergeFrom(input).buildParsed(); - } - public static com.alibaba.rocketmq.common.protocol.MQProtos.ProducerInfo parseFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return newBuilder().mergeFrom(input, extensionRegistry) - .buildParsed(); - } - public static com.alibaba.rocketmq.common.protocol.MQProtos.ProducerInfo parseDelimitedFrom(java.io.InputStream input) - throws java.io.IOException { - Builder builder = newBuilder(); - if (builder.mergeDelimitedFrom(input)) { - return builder.buildParsed(); - } else { - return null; - } - } - public static com.alibaba.rocketmq.common.protocol.MQProtos.ProducerInfo parseDelimitedFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - Builder builder = newBuilder(); - if (builder.mergeDelimitedFrom(input, extensionRegistry)) { - return builder.buildParsed(); - } else { - return null; - } - } - public static com.alibaba.rocketmq.common.protocol.MQProtos.ProducerInfo parseFrom( - com.google.protobuf.CodedInputStream input) - throws java.io.IOException { - return newBuilder().mergeFrom(input).buildParsed(); - } - public static com.alibaba.rocketmq.common.protocol.MQProtos.ProducerInfo parseFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return newBuilder().mergeFrom(input, extensionRegistry) - .buildParsed(); - } - - public static Builder newBuilder() { return Builder.create(); } - public Builder newBuilderForType() { return newBuilder(); } - public static Builder newBuilder(com.alibaba.rocketmq.common.protocol.MQProtos.ProducerInfo prototype) { - return newBuilder().mergeFrom(prototype); - } - public Builder toBuilder() { return newBuilder(this); } - - @java.lang.Override - protected Builder newBuilderForType( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - Builder builder = new Builder(parent); - return builder; - } - public static final class Builder extends - com.google.protobuf.GeneratedMessage.Builder - implements com.alibaba.rocketmq.common.protocol.MQProtos.ProducerInfoOrBuilder { - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return com.alibaba.rocketmq.common.protocol.MQProtos.internal_static_rocketmq_ProducerInfo_descriptor; - } - - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return com.alibaba.rocketmq.common.protocol.MQProtos.internal_static_rocketmq_ProducerInfo_fieldAccessorTable; - } - - // Construct using com.alibaba.rocketmq.common.protocol.MQProtos.ProducerInfo.newBuilder() - private Builder() { - maybeForceBuilderInitialization(); - } - - private Builder(BuilderParent parent) { - super(parent); - maybeForceBuilderInitialization(); - } - private void maybeForceBuilderInitialization() { - if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) { - } - } - private static Builder create() { - return new Builder(); - } - - public Builder clear() { - super.clear(); - groupName_ = ""; - bitField0_ = (bitField0_ & ~0x00000001); - return this; - } - - public Builder clone() { - return create().mergeFrom(buildPartial()); - } - - public com.google.protobuf.Descriptors.Descriptor - getDescriptorForType() { - return com.alibaba.rocketmq.common.protocol.MQProtos.ProducerInfo.getDescriptor(); - } - - public com.alibaba.rocketmq.common.protocol.MQProtos.ProducerInfo getDefaultInstanceForType() { - return com.alibaba.rocketmq.common.protocol.MQProtos.ProducerInfo.getDefaultInstance(); - } - - public com.alibaba.rocketmq.common.protocol.MQProtos.ProducerInfo build() { - com.alibaba.rocketmq.common.protocol.MQProtos.ProducerInfo result = buildPartial(); - if (!result.isInitialized()) { - throw newUninitializedMessageException(result); - } - return result; - } - - private com.alibaba.rocketmq.common.protocol.MQProtos.ProducerInfo buildParsed() - throws com.google.protobuf.InvalidProtocolBufferException { - com.alibaba.rocketmq.common.protocol.MQProtos.ProducerInfo result = buildPartial(); - if (!result.isInitialized()) { - throw newUninitializedMessageException( - result).asInvalidProtocolBufferException(); - } - return result; - } - - public com.alibaba.rocketmq.common.protocol.MQProtos.ProducerInfo buildPartial() { - com.alibaba.rocketmq.common.protocol.MQProtos.ProducerInfo result = new com.alibaba.rocketmq.common.protocol.MQProtos.ProducerInfo(this); - int from_bitField0_ = bitField0_; - int to_bitField0_ = 0; - if (((from_bitField0_ & 0x00000001) == 0x00000001)) { - to_bitField0_ |= 0x00000001; - } - result.groupName_ = groupName_; - result.bitField0_ = to_bitField0_; - onBuilt(); - return result; - } - - public Builder mergeFrom(com.google.protobuf.Message other) { - if (other instanceof com.alibaba.rocketmq.common.protocol.MQProtos.ProducerInfo) { - return mergeFrom((com.alibaba.rocketmq.common.protocol.MQProtos.ProducerInfo)other); - } else { - super.mergeFrom(other); - return this; - } - } - - public Builder mergeFrom(com.alibaba.rocketmq.common.protocol.MQProtos.ProducerInfo other) { - if (other == com.alibaba.rocketmq.common.protocol.MQProtos.ProducerInfo.getDefaultInstance()) return this; - if (other.hasGroupName()) { - setGroupName(other.getGroupName()); - } - this.mergeUnknownFields(other.getUnknownFields()); - return this; - } - - public final boolean isInitialized() { - if (!hasGroupName()) { - - return false; - } - return true; - } - - public Builder mergeFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - com.google.protobuf.UnknownFieldSet.Builder unknownFields = - com.google.protobuf.UnknownFieldSet.newBuilder( - this.getUnknownFields()); - while (true) { - int tag = input.readTag(); - switch (tag) { - case 0: - this.setUnknownFields(unknownFields.build()); - onChanged(); - return this; - default: { - if (!parseUnknownField(input, unknownFields, - extensionRegistry, tag)) { - this.setUnknownFields(unknownFields.build()); - onChanged(); - return this; - } - break; - } - case 10: { - bitField0_ |= 0x00000001; - groupName_ = input.readBytes(); - break; - } - } - } - } - - private int bitField0_; - - // required string groupName = 1; - private java.lang.Object groupName_ = ""; - public boolean hasGroupName() { - return ((bitField0_ & 0x00000001) == 0x00000001); - } - public String getGroupName() { - java.lang.Object ref = groupName_; - if (!(ref instanceof String)) { - String s = ((com.google.protobuf.ByteString) ref).toStringUtf8(); - groupName_ = s; - return s; - } else { - return (String) ref; - } - } - public Builder setGroupName(String value) { - if (value == null) { - throw new NullPointerException(); - } - bitField0_ |= 0x00000001; - groupName_ = value; - onChanged(); - return this; - } - public Builder clearGroupName() { - bitField0_ = (bitField0_ & ~0x00000001); - groupName_ = getDefaultInstance().getGroupName(); - onChanged(); - return this; - } - void setGroupName(com.google.protobuf.ByteString value) { - bitField0_ |= 0x00000001; - groupName_ = value; - onChanged(); - } - - // @@protoc_insertion_point(builder_scope:rocketmq.ProducerInfo) - } - - static { - defaultInstance = new ProducerInfo(true); - defaultInstance.initFields(); - } - - // @@protoc_insertion_point(class_scope:rocketmq.ProducerInfo) - } - - public interface SubscriptionInfoOrBuilder - extends com.google.protobuf.MessageOrBuilder { - - // required string topic = 1; - boolean hasTopic(); - String getTopic(); - - // required string subString = 2; - boolean hasSubString(); - String getSubString(); - - // required string subNumfmt = 3; - boolean hasSubNumfmt(); - String getSubNumfmt(); - - // required bool hasAndOperator = 4; - boolean hasHasAndOperator(); - boolean getHasAndOperator(); - } - public static final class SubscriptionInfo extends - com.google.protobuf.GeneratedMessage - implements SubscriptionInfoOrBuilder { - // Use SubscriptionInfo.newBuilder() to construct. - private SubscriptionInfo(Builder builder) { - super(builder); - } - private SubscriptionInfo(boolean noInit) {} - - private static final SubscriptionInfo defaultInstance; - public static SubscriptionInfo getDefaultInstance() { - return defaultInstance; - } - - public SubscriptionInfo getDefaultInstanceForType() { - return defaultInstance; - } - - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return com.alibaba.rocketmq.common.protocol.MQProtos.internal_static_rocketmq_SubscriptionInfo_descriptor; - } - - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return com.alibaba.rocketmq.common.protocol.MQProtos.internal_static_rocketmq_SubscriptionInfo_fieldAccessorTable; - } - - private int bitField0_; - // required string topic = 1; - public static final int TOPIC_FIELD_NUMBER = 1; - private java.lang.Object topic_; - public boolean hasTopic() { - return ((bitField0_ & 0x00000001) == 0x00000001); - } - public String getTopic() { - java.lang.Object ref = topic_; - if (ref instanceof String) { - return (String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - String s = bs.toStringUtf8(); - if (com.google.protobuf.Internal.isValidUtf8(bs)) { - topic_ = s; - } - return s; - } - } - private com.google.protobuf.ByteString getTopicBytes() { - java.lang.Object ref = topic_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8((String) ref); - topic_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - // required string subString = 2; - public static final int SUBSTRING_FIELD_NUMBER = 2; - private java.lang.Object subString_; - public boolean hasSubString() { - return ((bitField0_ & 0x00000002) == 0x00000002); - } - public String getSubString() { - java.lang.Object ref = subString_; - if (ref instanceof String) { - return (String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - String s = bs.toStringUtf8(); - if (com.google.protobuf.Internal.isValidUtf8(bs)) { - subString_ = s; - } - return s; - } - } - private com.google.protobuf.ByteString getSubStringBytes() { - java.lang.Object ref = subString_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8((String) ref); - subString_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - // required string subNumfmt = 3; - public static final int SUBNUMFMT_FIELD_NUMBER = 3; - private java.lang.Object subNumfmt_; - public boolean hasSubNumfmt() { - return ((bitField0_ & 0x00000004) == 0x00000004); - } - public String getSubNumfmt() { - java.lang.Object ref = subNumfmt_; - if (ref instanceof String) { - return (String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - String s = bs.toStringUtf8(); - if (com.google.protobuf.Internal.isValidUtf8(bs)) { - subNumfmt_ = s; - } - return s; - } - } - private com.google.protobuf.ByteString getSubNumfmtBytes() { - java.lang.Object ref = subNumfmt_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8((String) ref); - subNumfmt_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - // required bool hasAndOperator = 4; - public static final int HASANDOPERATOR_FIELD_NUMBER = 4; - private boolean hasAndOperator_; - public boolean hasHasAndOperator() { - return ((bitField0_ & 0x00000008) == 0x00000008); - } - public boolean getHasAndOperator() { - return hasAndOperator_; - } - - private void initFields() { - topic_ = ""; - subString_ = ""; - subNumfmt_ = ""; - hasAndOperator_ = false; - } - private byte memoizedIsInitialized = -1; - public final boolean isInitialized() { - byte isInitialized = memoizedIsInitialized; - if (isInitialized != -1) return isInitialized == 1; - - if (!hasTopic()) { - memoizedIsInitialized = 0; - return false; - } - if (!hasSubString()) { - memoizedIsInitialized = 0; - return false; - } - if (!hasSubNumfmt()) { - memoizedIsInitialized = 0; - return false; - } - if (!hasHasAndOperator()) { - memoizedIsInitialized = 0; - return false; - } - memoizedIsInitialized = 1; - return true; - } - - public void writeTo(com.google.protobuf.CodedOutputStream output) - throws java.io.IOException { - getSerializedSize(); - if (((bitField0_ & 0x00000001) == 0x00000001)) { - output.writeBytes(1, getTopicBytes()); - } - if (((bitField0_ & 0x00000002) == 0x00000002)) { - output.writeBytes(2, getSubStringBytes()); - } - if (((bitField0_ & 0x00000004) == 0x00000004)) { - output.writeBytes(3, getSubNumfmtBytes()); - } - if (((bitField0_ & 0x00000008) == 0x00000008)) { - output.writeBool(4, hasAndOperator_); - } - getUnknownFields().writeTo(output); - } - - private int memoizedSerializedSize = -1; - public int getSerializedSize() { - int size = memoizedSerializedSize; - if (size != -1) return size; - - size = 0; - if (((bitField0_ & 0x00000001) == 0x00000001)) { - size += com.google.protobuf.CodedOutputStream - .computeBytesSize(1, getTopicBytes()); - } - if (((bitField0_ & 0x00000002) == 0x00000002)) { - size += com.google.protobuf.CodedOutputStream - .computeBytesSize(2, getSubStringBytes()); - } - if (((bitField0_ & 0x00000004) == 0x00000004)) { - size += com.google.protobuf.CodedOutputStream - .computeBytesSize(3, getSubNumfmtBytes()); - } - if (((bitField0_ & 0x00000008) == 0x00000008)) { - size += com.google.protobuf.CodedOutputStream - .computeBoolSize(4, hasAndOperator_); - } - size += getUnknownFields().getSerializedSize(); - memoizedSerializedSize = size; - return size; - } - - private static final long serialVersionUID = 0L; - @java.lang.Override - protected java.lang.Object writeReplace() - throws java.io.ObjectStreamException { - return super.writeReplace(); - } - - public static com.alibaba.rocketmq.common.protocol.MQProtos.SubscriptionInfo parseFrom( - com.google.protobuf.ByteString data) - throws com.google.protobuf.InvalidProtocolBufferException { - return newBuilder().mergeFrom(data).buildParsed(); - } - public static com.alibaba.rocketmq.common.protocol.MQProtos.SubscriptionInfo parseFrom( - com.google.protobuf.ByteString data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return newBuilder().mergeFrom(data, extensionRegistry) - .buildParsed(); - } - public static com.alibaba.rocketmq.common.protocol.MQProtos.SubscriptionInfo parseFrom(byte[] data) - throws com.google.protobuf.InvalidProtocolBufferException { - return newBuilder().mergeFrom(data).buildParsed(); - } - public static com.alibaba.rocketmq.common.protocol.MQProtos.SubscriptionInfo parseFrom( - byte[] data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return newBuilder().mergeFrom(data, extensionRegistry) - .buildParsed(); - } - public static com.alibaba.rocketmq.common.protocol.MQProtos.SubscriptionInfo parseFrom(java.io.InputStream input) - throws java.io.IOException { - return newBuilder().mergeFrom(input).buildParsed(); - } - public static com.alibaba.rocketmq.common.protocol.MQProtos.SubscriptionInfo parseFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return newBuilder().mergeFrom(input, extensionRegistry) - .buildParsed(); - } - public static com.alibaba.rocketmq.common.protocol.MQProtos.SubscriptionInfo parseDelimitedFrom(java.io.InputStream input) - throws java.io.IOException { - Builder builder = newBuilder(); - if (builder.mergeDelimitedFrom(input)) { - return builder.buildParsed(); - } else { - return null; - } - } - public static com.alibaba.rocketmq.common.protocol.MQProtos.SubscriptionInfo parseDelimitedFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - Builder builder = newBuilder(); - if (builder.mergeDelimitedFrom(input, extensionRegistry)) { - return builder.buildParsed(); - } else { - return null; - } - } - public static com.alibaba.rocketmq.common.protocol.MQProtos.SubscriptionInfo parseFrom( - com.google.protobuf.CodedInputStream input) - throws java.io.IOException { - return newBuilder().mergeFrom(input).buildParsed(); - } - public static com.alibaba.rocketmq.common.protocol.MQProtos.SubscriptionInfo parseFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return newBuilder().mergeFrom(input, extensionRegistry) - .buildParsed(); - } - - public static Builder newBuilder() { return Builder.create(); } - public Builder newBuilderForType() { return newBuilder(); } - public static Builder newBuilder(com.alibaba.rocketmq.common.protocol.MQProtos.SubscriptionInfo prototype) { - return newBuilder().mergeFrom(prototype); - } - public Builder toBuilder() { return newBuilder(this); } - - @java.lang.Override - protected Builder newBuilderForType( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - Builder builder = new Builder(parent); - return builder; - } - public static final class Builder extends - com.google.protobuf.GeneratedMessage.Builder - implements com.alibaba.rocketmq.common.protocol.MQProtos.SubscriptionInfoOrBuilder { - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return com.alibaba.rocketmq.common.protocol.MQProtos.internal_static_rocketmq_SubscriptionInfo_descriptor; - } - - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return com.alibaba.rocketmq.common.protocol.MQProtos.internal_static_rocketmq_SubscriptionInfo_fieldAccessorTable; - } - - // Construct using com.alibaba.rocketmq.common.protocol.MQProtos.SubscriptionInfo.newBuilder() - private Builder() { - maybeForceBuilderInitialization(); - } - - private Builder(BuilderParent parent) { - super(parent); - maybeForceBuilderInitialization(); - } - private void maybeForceBuilderInitialization() { - if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) { - } - } - private static Builder create() { - return new Builder(); - } - - public Builder clear() { - super.clear(); - topic_ = ""; - bitField0_ = (bitField0_ & ~0x00000001); - subString_ = ""; - bitField0_ = (bitField0_ & ~0x00000002); - subNumfmt_ = ""; - bitField0_ = (bitField0_ & ~0x00000004); - hasAndOperator_ = false; - bitField0_ = (bitField0_ & ~0x00000008); - return this; - } - - public Builder clone() { - return create().mergeFrom(buildPartial()); - } - - public com.google.protobuf.Descriptors.Descriptor - getDescriptorForType() { - return com.alibaba.rocketmq.common.protocol.MQProtos.SubscriptionInfo.getDescriptor(); - } - - public com.alibaba.rocketmq.common.protocol.MQProtos.SubscriptionInfo getDefaultInstanceForType() { - return com.alibaba.rocketmq.common.protocol.MQProtos.SubscriptionInfo.getDefaultInstance(); - } - - public com.alibaba.rocketmq.common.protocol.MQProtos.SubscriptionInfo build() { - com.alibaba.rocketmq.common.protocol.MQProtos.SubscriptionInfo result = buildPartial(); - if (!result.isInitialized()) { - throw newUninitializedMessageException(result); - } - return result; - } - - private com.alibaba.rocketmq.common.protocol.MQProtos.SubscriptionInfo buildParsed() - throws com.google.protobuf.InvalidProtocolBufferException { - com.alibaba.rocketmq.common.protocol.MQProtos.SubscriptionInfo result = buildPartial(); - if (!result.isInitialized()) { - throw newUninitializedMessageException( - result).asInvalidProtocolBufferException(); - } - return result; - } - - public com.alibaba.rocketmq.common.protocol.MQProtos.SubscriptionInfo buildPartial() { - com.alibaba.rocketmq.common.protocol.MQProtos.SubscriptionInfo result = new com.alibaba.rocketmq.common.protocol.MQProtos.SubscriptionInfo(this); - int from_bitField0_ = bitField0_; - int to_bitField0_ = 0; - if (((from_bitField0_ & 0x00000001) == 0x00000001)) { - to_bitField0_ |= 0x00000001; - } - result.topic_ = topic_; - if (((from_bitField0_ & 0x00000002) == 0x00000002)) { - to_bitField0_ |= 0x00000002; - } - result.subString_ = subString_; - if (((from_bitField0_ & 0x00000004) == 0x00000004)) { - to_bitField0_ |= 0x00000004; - } - result.subNumfmt_ = subNumfmt_; - if (((from_bitField0_ & 0x00000008) == 0x00000008)) { - to_bitField0_ |= 0x00000008; - } - result.hasAndOperator_ = hasAndOperator_; - result.bitField0_ = to_bitField0_; - onBuilt(); - return result; - } - - public Builder mergeFrom(com.google.protobuf.Message other) { - if (other instanceof com.alibaba.rocketmq.common.protocol.MQProtos.SubscriptionInfo) { - return mergeFrom((com.alibaba.rocketmq.common.protocol.MQProtos.SubscriptionInfo)other); - } else { - super.mergeFrom(other); - return this; - } - } - - public Builder mergeFrom(com.alibaba.rocketmq.common.protocol.MQProtos.SubscriptionInfo other) { - if (other == com.alibaba.rocketmq.common.protocol.MQProtos.SubscriptionInfo.getDefaultInstance()) return this; - if (other.hasTopic()) { - setTopic(other.getTopic()); - } - if (other.hasSubString()) { - setSubString(other.getSubString()); - } - if (other.hasSubNumfmt()) { - setSubNumfmt(other.getSubNumfmt()); - } - if (other.hasHasAndOperator()) { - setHasAndOperator(other.getHasAndOperator()); - } - this.mergeUnknownFields(other.getUnknownFields()); - return this; - } - - public final boolean isInitialized() { - if (!hasTopic()) { - - return false; - } - if (!hasSubString()) { - - return false; - } - if (!hasSubNumfmt()) { - - return false; - } - if (!hasHasAndOperator()) { - - return false; - } - return true; - } - - public Builder mergeFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - com.google.protobuf.UnknownFieldSet.Builder unknownFields = - com.google.protobuf.UnknownFieldSet.newBuilder( - this.getUnknownFields()); - while (true) { - int tag = input.readTag(); - switch (tag) { - case 0: - this.setUnknownFields(unknownFields.build()); - onChanged(); - return this; - default: { - if (!parseUnknownField(input, unknownFields, - extensionRegistry, tag)) { - this.setUnknownFields(unknownFields.build()); - onChanged(); - return this; - } - break; - } - case 10: { - bitField0_ |= 0x00000001; - topic_ = input.readBytes(); - break; - } - case 18: { - bitField0_ |= 0x00000002; - subString_ = input.readBytes(); - break; - } - case 26: { - bitField0_ |= 0x00000004; - subNumfmt_ = input.readBytes(); - break; - } - case 32: { - bitField0_ |= 0x00000008; - hasAndOperator_ = input.readBool(); - break; - } - } - } - } - - private int bitField0_; - - // required string topic = 1; - private java.lang.Object topic_ = ""; - public boolean hasTopic() { - return ((bitField0_ & 0x00000001) == 0x00000001); - } - public String getTopic() { - java.lang.Object ref = topic_; - if (!(ref instanceof String)) { - String s = ((com.google.protobuf.ByteString) ref).toStringUtf8(); - topic_ = s; - return s; - } else { - return (String) ref; - } - } - public Builder setTopic(String value) { - if (value == null) { - throw new NullPointerException(); - } - bitField0_ |= 0x00000001; - topic_ = value; - onChanged(); - return this; - } - public Builder clearTopic() { - bitField0_ = (bitField0_ & ~0x00000001); - topic_ = getDefaultInstance().getTopic(); - onChanged(); - return this; - } - void setTopic(com.google.protobuf.ByteString value) { - bitField0_ |= 0x00000001; - topic_ = value; - onChanged(); - } - - // required string subString = 2; - private java.lang.Object subString_ = ""; - public boolean hasSubString() { - return ((bitField0_ & 0x00000002) == 0x00000002); - } - public String getSubString() { - java.lang.Object ref = subString_; - if (!(ref instanceof String)) { - String s = ((com.google.protobuf.ByteString) ref).toStringUtf8(); - subString_ = s; - return s; - } else { - return (String) ref; - } - } - public Builder setSubString(String value) { - if (value == null) { - throw new NullPointerException(); - } - bitField0_ |= 0x00000002; - subString_ = value; - onChanged(); - return this; - } - public Builder clearSubString() { - bitField0_ = (bitField0_ & ~0x00000002); - subString_ = getDefaultInstance().getSubString(); - onChanged(); - return this; - } - void setSubString(com.google.protobuf.ByteString value) { - bitField0_ |= 0x00000002; - subString_ = value; - onChanged(); - } - - // required string subNumfmt = 3; - private java.lang.Object subNumfmt_ = ""; - public boolean hasSubNumfmt() { - return ((bitField0_ & 0x00000004) == 0x00000004); - } - public String getSubNumfmt() { - java.lang.Object ref = subNumfmt_; - if (!(ref instanceof String)) { - String s = ((com.google.protobuf.ByteString) ref).toStringUtf8(); - subNumfmt_ = s; - return s; - } else { - return (String) ref; - } - } - public Builder setSubNumfmt(String value) { - if (value == null) { - throw new NullPointerException(); - } - bitField0_ |= 0x00000004; - subNumfmt_ = value; - onChanged(); - return this; - } - public Builder clearSubNumfmt() { - bitField0_ = (bitField0_ & ~0x00000004); - subNumfmt_ = getDefaultInstance().getSubNumfmt(); - onChanged(); - return this; - } - void setSubNumfmt(com.google.protobuf.ByteString value) { - bitField0_ |= 0x00000004; - subNumfmt_ = value; - onChanged(); - } - - // required bool hasAndOperator = 4; - private boolean hasAndOperator_ ; - public boolean hasHasAndOperator() { - return ((bitField0_ & 0x00000008) == 0x00000008); - } - public boolean getHasAndOperator() { - return hasAndOperator_; - } - public Builder setHasAndOperator(boolean value) { - bitField0_ |= 0x00000008; - hasAndOperator_ = value; - onChanged(); - return this; - } - public Builder clearHasAndOperator() { - bitField0_ = (bitField0_ & ~0x00000008); - hasAndOperator_ = false; - onChanged(); - return this; - } - - // @@protoc_insertion_point(builder_scope:rocketmq.SubscriptionInfo) - } - - static { - defaultInstance = new SubscriptionInfo(true); - defaultInstance.initFields(); - } - - // @@protoc_insertion_point(class_scope:rocketmq.SubscriptionInfo) - } - - public interface ConsumerInfoOrBuilder - extends com.google.protobuf.MessageOrBuilder { - - // required string groupName = 1; - boolean hasGroupName(); - String getGroupName(); - - // required string consumeType = 2; - boolean hasConsumeType(); - String getConsumeType(); - - // required string messageModel = 3; - boolean hasMessageModel(); - String getMessageModel(); - - // repeated .rocketmq.SubscriptionInfo subscriptionInfos = 4; - java.util.List - getSubscriptionInfosList(); - com.alibaba.rocketmq.common.protocol.MQProtos.SubscriptionInfo getSubscriptionInfos(int index); - int getSubscriptionInfosCount(); - java.util.List - getSubscriptionInfosOrBuilderList(); - com.alibaba.rocketmq.common.protocol.MQProtos.SubscriptionInfoOrBuilder getSubscriptionInfosOrBuilder( - int index); - } - public static final class ConsumerInfo extends - com.google.protobuf.GeneratedMessage - implements ConsumerInfoOrBuilder { - // Use ConsumerInfo.newBuilder() to construct. - private ConsumerInfo(Builder builder) { - super(builder); - } - private ConsumerInfo(boolean noInit) {} - - private static final ConsumerInfo defaultInstance; - public static ConsumerInfo getDefaultInstance() { - return defaultInstance; - } - - public ConsumerInfo getDefaultInstanceForType() { - return defaultInstance; - } - - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return com.alibaba.rocketmq.common.protocol.MQProtos.internal_static_rocketmq_ConsumerInfo_descriptor; - } - - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return com.alibaba.rocketmq.common.protocol.MQProtos.internal_static_rocketmq_ConsumerInfo_fieldAccessorTable; - } - - private int bitField0_; - // required string groupName = 1; - public static final int GROUPNAME_FIELD_NUMBER = 1; - private java.lang.Object groupName_; - public boolean hasGroupName() { - return ((bitField0_ & 0x00000001) == 0x00000001); - } - public String getGroupName() { - java.lang.Object ref = groupName_; - if (ref instanceof String) { - return (String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - String s = bs.toStringUtf8(); - if (com.google.protobuf.Internal.isValidUtf8(bs)) { - groupName_ = s; - } - return s; - } - } - private com.google.protobuf.ByteString getGroupNameBytes() { - java.lang.Object ref = groupName_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8((String) ref); - groupName_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - // required string consumeType = 2; - public static final int CONSUMETYPE_FIELD_NUMBER = 2; - private java.lang.Object consumeType_; - public boolean hasConsumeType() { - return ((bitField0_ & 0x00000002) == 0x00000002); - } - public String getConsumeType() { - java.lang.Object ref = consumeType_; - if (ref instanceof String) { - return (String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - String s = bs.toStringUtf8(); - if (com.google.protobuf.Internal.isValidUtf8(bs)) { - consumeType_ = s; - } - return s; - } - } - private com.google.protobuf.ByteString getConsumeTypeBytes() { - java.lang.Object ref = consumeType_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8((String) ref); - consumeType_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - // required string messageModel = 3; - public static final int MESSAGEMODEL_FIELD_NUMBER = 3; - private java.lang.Object messageModel_; - public boolean hasMessageModel() { - return ((bitField0_ & 0x00000004) == 0x00000004); - } - public String getMessageModel() { - java.lang.Object ref = messageModel_; - if (ref instanceof String) { - return (String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - String s = bs.toStringUtf8(); - if (com.google.protobuf.Internal.isValidUtf8(bs)) { - messageModel_ = s; - } - return s; - } - } - private com.google.protobuf.ByteString getMessageModelBytes() { - java.lang.Object ref = messageModel_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8((String) ref); - messageModel_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - // repeated .rocketmq.SubscriptionInfo subscriptionInfos = 4; - public static final int SUBSCRIPTIONINFOS_FIELD_NUMBER = 4; - private java.util.List subscriptionInfos_; - public java.util.List getSubscriptionInfosList() { - return subscriptionInfos_; - } - public java.util.List - getSubscriptionInfosOrBuilderList() { - return subscriptionInfos_; - } - public int getSubscriptionInfosCount() { - return subscriptionInfos_.size(); - } - public com.alibaba.rocketmq.common.protocol.MQProtos.SubscriptionInfo getSubscriptionInfos(int index) { - return subscriptionInfos_.get(index); - } - public com.alibaba.rocketmq.common.protocol.MQProtos.SubscriptionInfoOrBuilder getSubscriptionInfosOrBuilder( - int index) { - return subscriptionInfos_.get(index); - } - - private void initFields() { - groupName_ = ""; - consumeType_ = ""; - messageModel_ = ""; - subscriptionInfos_ = java.util.Collections.emptyList(); - } - private byte memoizedIsInitialized = -1; - public final boolean isInitialized() { - byte isInitialized = memoizedIsInitialized; - if (isInitialized != -1) return isInitialized == 1; - - if (!hasGroupName()) { - memoizedIsInitialized = 0; - return false; - } - if (!hasConsumeType()) { - memoizedIsInitialized = 0; - return false; - } - if (!hasMessageModel()) { - memoizedIsInitialized = 0; - return false; - } - for (int i = 0; i < getSubscriptionInfosCount(); i++) { - if (!getSubscriptionInfos(i).isInitialized()) { - memoizedIsInitialized = 0; - return false; - } - } - memoizedIsInitialized = 1; - return true; - } - - public void writeTo(com.google.protobuf.CodedOutputStream output) - throws java.io.IOException { - getSerializedSize(); - if (((bitField0_ & 0x00000001) == 0x00000001)) { - output.writeBytes(1, getGroupNameBytes()); - } - if (((bitField0_ & 0x00000002) == 0x00000002)) { - output.writeBytes(2, getConsumeTypeBytes()); - } - if (((bitField0_ & 0x00000004) == 0x00000004)) { - output.writeBytes(3, getMessageModelBytes()); - } - for (int i = 0; i < subscriptionInfos_.size(); i++) { - output.writeMessage(4, subscriptionInfos_.get(i)); - } - getUnknownFields().writeTo(output); - } - - private int memoizedSerializedSize = -1; - public int getSerializedSize() { - int size = memoizedSerializedSize; - if (size != -1) return size; - - size = 0; - if (((bitField0_ & 0x00000001) == 0x00000001)) { - size += com.google.protobuf.CodedOutputStream - .computeBytesSize(1, getGroupNameBytes()); - } - if (((bitField0_ & 0x00000002) == 0x00000002)) { - size += com.google.protobuf.CodedOutputStream - .computeBytesSize(2, getConsumeTypeBytes()); - } - if (((bitField0_ & 0x00000004) == 0x00000004)) { - size += com.google.protobuf.CodedOutputStream - .computeBytesSize(3, getMessageModelBytes()); - } - for (int i = 0; i < subscriptionInfos_.size(); i++) { - size += com.google.protobuf.CodedOutputStream - .computeMessageSize(4, subscriptionInfos_.get(i)); - } - size += getUnknownFields().getSerializedSize(); - memoizedSerializedSize = size; - return size; - } - - private static final long serialVersionUID = 0L; - @java.lang.Override - protected java.lang.Object writeReplace() - throws java.io.ObjectStreamException { - return super.writeReplace(); - } - - public static com.alibaba.rocketmq.common.protocol.MQProtos.ConsumerInfo parseFrom( - com.google.protobuf.ByteString data) - throws com.google.protobuf.InvalidProtocolBufferException { - return newBuilder().mergeFrom(data).buildParsed(); - } - public static com.alibaba.rocketmq.common.protocol.MQProtos.ConsumerInfo parseFrom( - com.google.protobuf.ByteString data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return newBuilder().mergeFrom(data, extensionRegistry) - .buildParsed(); - } - public static com.alibaba.rocketmq.common.protocol.MQProtos.ConsumerInfo parseFrom(byte[] data) - throws com.google.protobuf.InvalidProtocolBufferException { - return newBuilder().mergeFrom(data).buildParsed(); - } - public static com.alibaba.rocketmq.common.protocol.MQProtos.ConsumerInfo parseFrom( - byte[] data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return newBuilder().mergeFrom(data, extensionRegistry) - .buildParsed(); - } - public static com.alibaba.rocketmq.common.protocol.MQProtos.ConsumerInfo parseFrom(java.io.InputStream input) - throws java.io.IOException { - return newBuilder().mergeFrom(input).buildParsed(); - } - public static com.alibaba.rocketmq.common.protocol.MQProtos.ConsumerInfo parseFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return newBuilder().mergeFrom(input, extensionRegistry) - .buildParsed(); - } - public static com.alibaba.rocketmq.common.protocol.MQProtos.ConsumerInfo parseDelimitedFrom(java.io.InputStream input) - throws java.io.IOException { - Builder builder = newBuilder(); - if (builder.mergeDelimitedFrom(input)) { - return builder.buildParsed(); - } else { - return null; - } - } - public static com.alibaba.rocketmq.common.protocol.MQProtos.ConsumerInfo parseDelimitedFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - Builder builder = newBuilder(); - if (builder.mergeDelimitedFrom(input, extensionRegistry)) { - return builder.buildParsed(); - } else { - return null; - } - } - public static com.alibaba.rocketmq.common.protocol.MQProtos.ConsumerInfo parseFrom( - com.google.protobuf.CodedInputStream input) - throws java.io.IOException { - return newBuilder().mergeFrom(input).buildParsed(); - } - public static com.alibaba.rocketmq.common.protocol.MQProtos.ConsumerInfo parseFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return newBuilder().mergeFrom(input, extensionRegistry) - .buildParsed(); - } - - public static Builder newBuilder() { return Builder.create(); } - public Builder newBuilderForType() { return newBuilder(); } - public static Builder newBuilder(com.alibaba.rocketmq.common.protocol.MQProtos.ConsumerInfo prototype) { - return newBuilder().mergeFrom(prototype); - } - public Builder toBuilder() { return newBuilder(this); } - - @java.lang.Override - protected Builder newBuilderForType( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - Builder builder = new Builder(parent); - return builder; - } - public static final class Builder extends - com.google.protobuf.GeneratedMessage.Builder - implements com.alibaba.rocketmq.common.protocol.MQProtos.ConsumerInfoOrBuilder { - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return com.alibaba.rocketmq.common.protocol.MQProtos.internal_static_rocketmq_ConsumerInfo_descriptor; - } - - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return com.alibaba.rocketmq.common.protocol.MQProtos.internal_static_rocketmq_ConsumerInfo_fieldAccessorTable; - } - - // Construct using com.alibaba.rocketmq.common.protocol.MQProtos.ConsumerInfo.newBuilder() - private Builder() { - maybeForceBuilderInitialization(); - } - - private Builder(BuilderParent parent) { - super(parent); - maybeForceBuilderInitialization(); - } - private void maybeForceBuilderInitialization() { - if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) { - getSubscriptionInfosFieldBuilder(); - } - } - private static Builder create() { - return new Builder(); - } - - public Builder clear() { - super.clear(); - groupName_ = ""; - bitField0_ = (bitField0_ & ~0x00000001); - consumeType_ = ""; - bitField0_ = (bitField0_ & ~0x00000002); - messageModel_ = ""; - bitField0_ = (bitField0_ & ~0x00000004); - if (subscriptionInfosBuilder_ == null) { - subscriptionInfos_ = java.util.Collections.emptyList(); - bitField0_ = (bitField0_ & ~0x00000008); - } else { - subscriptionInfosBuilder_.clear(); - } - return this; - } - - public Builder clone() { - return create().mergeFrom(buildPartial()); - } - - public com.google.protobuf.Descriptors.Descriptor - getDescriptorForType() { - return com.alibaba.rocketmq.common.protocol.MQProtos.ConsumerInfo.getDescriptor(); - } - - public com.alibaba.rocketmq.common.protocol.MQProtos.ConsumerInfo getDefaultInstanceForType() { - return com.alibaba.rocketmq.common.protocol.MQProtos.ConsumerInfo.getDefaultInstance(); - } - - public com.alibaba.rocketmq.common.protocol.MQProtos.ConsumerInfo build() { - com.alibaba.rocketmq.common.protocol.MQProtos.ConsumerInfo result = buildPartial(); - if (!result.isInitialized()) { - throw newUninitializedMessageException(result); - } - return result; - } - - private com.alibaba.rocketmq.common.protocol.MQProtos.ConsumerInfo buildParsed() - throws com.google.protobuf.InvalidProtocolBufferException { - com.alibaba.rocketmq.common.protocol.MQProtos.ConsumerInfo result = buildPartial(); - if (!result.isInitialized()) { - throw newUninitializedMessageException( - result).asInvalidProtocolBufferException(); - } - return result; - } - - public com.alibaba.rocketmq.common.protocol.MQProtos.ConsumerInfo buildPartial() { - com.alibaba.rocketmq.common.protocol.MQProtos.ConsumerInfo result = new com.alibaba.rocketmq.common.protocol.MQProtos.ConsumerInfo(this); - int from_bitField0_ = bitField0_; - int to_bitField0_ = 0; - if (((from_bitField0_ & 0x00000001) == 0x00000001)) { - to_bitField0_ |= 0x00000001; - } - result.groupName_ = groupName_; - if (((from_bitField0_ & 0x00000002) == 0x00000002)) { - to_bitField0_ |= 0x00000002; - } - result.consumeType_ = consumeType_; - if (((from_bitField0_ & 0x00000004) == 0x00000004)) { - to_bitField0_ |= 0x00000004; - } - result.messageModel_ = messageModel_; - if (subscriptionInfosBuilder_ == null) { - if (((bitField0_ & 0x00000008) == 0x00000008)) { - subscriptionInfos_ = java.util.Collections.unmodifiableList(subscriptionInfos_); - bitField0_ = (bitField0_ & ~0x00000008); - } - result.subscriptionInfos_ = subscriptionInfos_; - } else { - result.subscriptionInfos_ = subscriptionInfosBuilder_.build(); - } - result.bitField0_ = to_bitField0_; - onBuilt(); - return result; - } - - public Builder mergeFrom(com.google.protobuf.Message other) { - if (other instanceof com.alibaba.rocketmq.common.protocol.MQProtos.ConsumerInfo) { - return mergeFrom((com.alibaba.rocketmq.common.protocol.MQProtos.ConsumerInfo)other); - } else { - super.mergeFrom(other); - return this; - } - } - - public Builder mergeFrom(com.alibaba.rocketmq.common.protocol.MQProtos.ConsumerInfo other) { - if (other == com.alibaba.rocketmq.common.protocol.MQProtos.ConsumerInfo.getDefaultInstance()) return this; - if (other.hasGroupName()) { - setGroupName(other.getGroupName()); - } - if (other.hasConsumeType()) { - setConsumeType(other.getConsumeType()); - } - if (other.hasMessageModel()) { - setMessageModel(other.getMessageModel()); - } - if (subscriptionInfosBuilder_ == null) { - if (!other.subscriptionInfos_.isEmpty()) { - if (subscriptionInfos_.isEmpty()) { - subscriptionInfos_ = other.subscriptionInfos_; - bitField0_ = (bitField0_ & ~0x00000008); - } else { - ensureSubscriptionInfosIsMutable(); - subscriptionInfos_.addAll(other.subscriptionInfos_); - } - onChanged(); - } - } else { - if (!other.subscriptionInfos_.isEmpty()) { - if (subscriptionInfosBuilder_.isEmpty()) { - subscriptionInfosBuilder_.dispose(); - subscriptionInfosBuilder_ = null; - subscriptionInfos_ = other.subscriptionInfos_; - bitField0_ = (bitField0_ & ~0x00000008); - subscriptionInfosBuilder_ = - com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders ? - getSubscriptionInfosFieldBuilder() : null; - } else { - subscriptionInfosBuilder_.addAllMessages(other.subscriptionInfos_); - } - } - } - this.mergeUnknownFields(other.getUnknownFields()); - return this; - } - - public final boolean isInitialized() { - if (!hasGroupName()) { - - return false; - } - if (!hasConsumeType()) { - - return false; - } - if (!hasMessageModel()) { - - return false; - } - for (int i = 0; i < getSubscriptionInfosCount(); i++) { - if (!getSubscriptionInfos(i).isInitialized()) { - - return false; - } - } - return true; - } - - public Builder mergeFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - com.google.protobuf.UnknownFieldSet.Builder unknownFields = - com.google.protobuf.UnknownFieldSet.newBuilder( - this.getUnknownFields()); - while (true) { - int tag = input.readTag(); - switch (tag) { - case 0: - this.setUnknownFields(unknownFields.build()); - onChanged(); - return this; - default: { - if (!parseUnknownField(input, unknownFields, - extensionRegistry, tag)) { - this.setUnknownFields(unknownFields.build()); - onChanged(); - return this; - } - break; - } - case 10: { - bitField0_ |= 0x00000001; - groupName_ = input.readBytes(); - break; - } - case 18: { - bitField0_ |= 0x00000002; - consumeType_ = input.readBytes(); - break; - } - case 26: { - bitField0_ |= 0x00000004; - messageModel_ = input.readBytes(); - break; - } - case 34: { - com.alibaba.rocketmq.common.protocol.MQProtos.SubscriptionInfo.Builder subBuilder = com.alibaba.rocketmq.common.protocol.MQProtos.SubscriptionInfo.newBuilder(); - input.readMessage(subBuilder, extensionRegistry); - addSubscriptionInfos(subBuilder.buildPartial()); - break; - } - } - } - } - - private int bitField0_; - - // required string groupName = 1; - private java.lang.Object groupName_ = ""; - public boolean hasGroupName() { - return ((bitField0_ & 0x00000001) == 0x00000001); - } - public String getGroupName() { - java.lang.Object ref = groupName_; - if (!(ref instanceof String)) { - String s = ((com.google.protobuf.ByteString) ref).toStringUtf8(); - groupName_ = s; - return s; - } else { - return (String) ref; - } - } - public Builder setGroupName(String value) { - if (value == null) { - throw new NullPointerException(); - } - bitField0_ |= 0x00000001; - groupName_ = value; - onChanged(); - return this; - } - public Builder clearGroupName() { - bitField0_ = (bitField0_ & ~0x00000001); - groupName_ = getDefaultInstance().getGroupName(); - onChanged(); - return this; - } - void setGroupName(com.google.protobuf.ByteString value) { - bitField0_ |= 0x00000001; - groupName_ = value; - onChanged(); - } - - // required string consumeType = 2; - private java.lang.Object consumeType_ = ""; - public boolean hasConsumeType() { - return ((bitField0_ & 0x00000002) == 0x00000002); - } - public String getConsumeType() { - java.lang.Object ref = consumeType_; - if (!(ref instanceof String)) { - String s = ((com.google.protobuf.ByteString) ref).toStringUtf8(); - consumeType_ = s; - return s; - } else { - return (String) ref; - } - } - public Builder setConsumeType(String value) { - if (value == null) { - throw new NullPointerException(); - } - bitField0_ |= 0x00000002; - consumeType_ = value; - onChanged(); - return this; - } - public Builder clearConsumeType() { - bitField0_ = (bitField0_ & ~0x00000002); - consumeType_ = getDefaultInstance().getConsumeType(); - onChanged(); - return this; - } - void setConsumeType(com.google.protobuf.ByteString value) { - bitField0_ |= 0x00000002; - consumeType_ = value; - onChanged(); - } - - // required string messageModel = 3; - private java.lang.Object messageModel_ = ""; - public boolean hasMessageModel() { - return ((bitField0_ & 0x00000004) == 0x00000004); - } - public String getMessageModel() { - java.lang.Object ref = messageModel_; - if (!(ref instanceof String)) { - String s = ((com.google.protobuf.ByteString) ref).toStringUtf8(); - messageModel_ = s; - return s; - } else { - return (String) ref; - } - } - public Builder setMessageModel(String value) { - if (value == null) { - throw new NullPointerException(); - } - bitField0_ |= 0x00000004; - messageModel_ = value; - onChanged(); - return this; - } - public Builder clearMessageModel() { - bitField0_ = (bitField0_ & ~0x00000004); - messageModel_ = getDefaultInstance().getMessageModel(); - onChanged(); - return this; - } - void setMessageModel(com.google.protobuf.ByteString value) { - bitField0_ |= 0x00000004; - messageModel_ = value; - onChanged(); - } - - // repeated .rocketmq.SubscriptionInfo subscriptionInfos = 4; - private java.util.List subscriptionInfos_ = - java.util.Collections.emptyList(); - private void ensureSubscriptionInfosIsMutable() { - if (!((bitField0_ & 0x00000008) == 0x00000008)) { - subscriptionInfos_ = new java.util.ArrayList(subscriptionInfos_); - bitField0_ |= 0x00000008; - } - } - - private com.google.protobuf.RepeatedFieldBuilder< - com.alibaba.rocketmq.common.protocol.MQProtos.SubscriptionInfo, com.alibaba.rocketmq.common.protocol.MQProtos.SubscriptionInfo.Builder, com.alibaba.rocketmq.common.protocol.MQProtos.SubscriptionInfoOrBuilder> subscriptionInfosBuilder_; - - public java.util.List getSubscriptionInfosList() { - if (subscriptionInfosBuilder_ == null) { - return java.util.Collections.unmodifiableList(subscriptionInfos_); - } else { - return subscriptionInfosBuilder_.getMessageList(); - } - } - public int getSubscriptionInfosCount() { - if (subscriptionInfosBuilder_ == null) { - return subscriptionInfos_.size(); - } else { - return subscriptionInfosBuilder_.getCount(); - } - } - public com.alibaba.rocketmq.common.protocol.MQProtos.SubscriptionInfo getSubscriptionInfos(int index) { - if (subscriptionInfosBuilder_ == null) { - return subscriptionInfos_.get(index); - } else { - return subscriptionInfosBuilder_.getMessage(index); - } - } - public Builder setSubscriptionInfos( - int index, com.alibaba.rocketmq.common.protocol.MQProtos.SubscriptionInfo value) { - if (subscriptionInfosBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - ensureSubscriptionInfosIsMutable(); - subscriptionInfos_.set(index, value); - onChanged(); - } else { - subscriptionInfosBuilder_.setMessage(index, value); - } - return this; - } - public Builder setSubscriptionInfos( - int index, com.alibaba.rocketmq.common.protocol.MQProtos.SubscriptionInfo.Builder builderForValue) { - if (subscriptionInfosBuilder_ == null) { - ensureSubscriptionInfosIsMutable(); - subscriptionInfos_.set(index, builderForValue.build()); - onChanged(); - } else { - subscriptionInfosBuilder_.setMessage(index, builderForValue.build()); - } - return this; - } - public Builder addSubscriptionInfos(com.alibaba.rocketmq.common.protocol.MQProtos.SubscriptionInfo value) { - if (subscriptionInfosBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - ensureSubscriptionInfosIsMutable(); - subscriptionInfos_.add(value); - onChanged(); - } else { - subscriptionInfosBuilder_.addMessage(value); - } - return this; - } - public Builder addSubscriptionInfos( - int index, com.alibaba.rocketmq.common.protocol.MQProtos.SubscriptionInfo value) { - if (subscriptionInfosBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - ensureSubscriptionInfosIsMutable(); - subscriptionInfos_.add(index, value); - onChanged(); - } else { - subscriptionInfosBuilder_.addMessage(index, value); - } - return this; - } - public Builder addSubscriptionInfos( - com.alibaba.rocketmq.common.protocol.MQProtos.SubscriptionInfo.Builder builderForValue) { - if (subscriptionInfosBuilder_ == null) { - ensureSubscriptionInfosIsMutable(); - subscriptionInfos_.add(builderForValue.build()); - onChanged(); - } else { - subscriptionInfosBuilder_.addMessage(builderForValue.build()); - } - return this; - } - public Builder addSubscriptionInfos( - int index, com.alibaba.rocketmq.common.protocol.MQProtos.SubscriptionInfo.Builder builderForValue) { - if (subscriptionInfosBuilder_ == null) { - ensureSubscriptionInfosIsMutable(); - subscriptionInfos_.add(index, builderForValue.build()); - onChanged(); - } else { - subscriptionInfosBuilder_.addMessage(index, builderForValue.build()); - } - return this; - } - public Builder addAllSubscriptionInfos( - java.lang.Iterable values) { - if (subscriptionInfosBuilder_ == null) { - ensureSubscriptionInfosIsMutable(); - super.addAll(values, subscriptionInfos_); - onChanged(); - } else { - subscriptionInfosBuilder_.addAllMessages(values); - } - return this; - } - public Builder clearSubscriptionInfos() { - if (subscriptionInfosBuilder_ == null) { - subscriptionInfos_ = java.util.Collections.emptyList(); - bitField0_ = (bitField0_ & ~0x00000008); - onChanged(); - } else { - subscriptionInfosBuilder_.clear(); - } - return this; - } - public Builder removeSubscriptionInfos(int index) { - if (subscriptionInfosBuilder_ == null) { - ensureSubscriptionInfosIsMutable(); - subscriptionInfos_.remove(index); - onChanged(); - } else { - subscriptionInfosBuilder_.remove(index); - } - return this; - } - public com.alibaba.rocketmq.common.protocol.MQProtos.SubscriptionInfo.Builder getSubscriptionInfosBuilder( - int index) { - return getSubscriptionInfosFieldBuilder().getBuilder(index); - } - public com.alibaba.rocketmq.common.protocol.MQProtos.SubscriptionInfoOrBuilder getSubscriptionInfosOrBuilder( - int index) { - if (subscriptionInfosBuilder_ == null) { - return subscriptionInfos_.get(index); } else { - return subscriptionInfosBuilder_.getMessageOrBuilder(index); - } - } - public java.util.List - getSubscriptionInfosOrBuilderList() { - if (subscriptionInfosBuilder_ != null) { - return subscriptionInfosBuilder_.getMessageOrBuilderList(); - } else { - return java.util.Collections.unmodifiableList(subscriptionInfos_); - } - } - public com.alibaba.rocketmq.common.protocol.MQProtos.SubscriptionInfo.Builder addSubscriptionInfosBuilder() { - return getSubscriptionInfosFieldBuilder().addBuilder( - com.alibaba.rocketmq.common.protocol.MQProtos.SubscriptionInfo.getDefaultInstance()); - } - public com.alibaba.rocketmq.common.protocol.MQProtos.SubscriptionInfo.Builder addSubscriptionInfosBuilder( - int index) { - return getSubscriptionInfosFieldBuilder().addBuilder( - index, com.alibaba.rocketmq.common.protocol.MQProtos.SubscriptionInfo.getDefaultInstance()); - } - public java.util.List - getSubscriptionInfosBuilderList() { - return getSubscriptionInfosFieldBuilder().getBuilderList(); - } - private com.google.protobuf.RepeatedFieldBuilder< - com.alibaba.rocketmq.common.protocol.MQProtos.SubscriptionInfo, com.alibaba.rocketmq.common.protocol.MQProtos.SubscriptionInfo.Builder, com.alibaba.rocketmq.common.protocol.MQProtos.SubscriptionInfoOrBuilder> - getSubscriptionInfosFieldBuilder() { - if (subscriptionInfosBuilder_ == null) { - subscriptionInfosBuilder_ = new com.google.protobuf.RepeatedFieldBuilder< - com.alibaba.rocketmq.common.protocol.MQProtos.SubscriptionInfo, com.alibaba.rocketmq.common.protocol.MQProtos.SubscriptionInfo.Builder, com.alibaba.rocketmq.common.protocol.MQProtos.SubscriptionInfoOrBuilder>( - subscriptionInfos_, - ((bitField0_ & 0x00000008) == 0x00000008), - getParentForChildren(), - isClean()); - subscriptionInfos_ = null; - } - return subscriptionInfosBuilder_; - } - - // @@protoc_insertion_point(builder_scope:rocketmq.ConsumerInfo) - } - - static { - defaultInstance = new ConsumerInfo(true); - defaultInstance.initFields(); - } - - // @@protoc_insertion_point(class_scope:rocketmq.ConsumerInfo) - } - - public interface HeartbeatInfoOrBuilder - extends com.google.protobuf.MessageOrBuilder { - - // required string clientID = 1; - boolean hasClientID(); - String getClientID(); - - // repeated .rocketmq.ProducerInfo producerInfos = 2; - java.util.List - getProducerInfosList(); - com.alibaba.rocketmq.common.protocol.MQProtos.ProducerInfo getProducerInfos(int index); - int getProducerInfosCount(); - java.util.List - getProducerInfosOrBuilderList(); - com.alibaba.rocketmq.common.protocol.MQProtos.ProducerInfoOrBuilder getProducerInfosOrBuilder( - int index); - - // repeated .rocketmq.ConsumerInfo consumerInfos = 3; - java.util.List - getConsumerInfosList(); - com.alibaba.rocketmq.common.protocol.MQProtos.ConsumerInfo getConsumerInfos(int index); - int getConsumerInfosCount(); - java.util.List - getConsumerInfosOrBuilderList(); - com.alibaba.rocketmq.common.protocol.MQProtos.ConsumerInfoOrBuilder getConsumerInfosOrBuilder( - int index); - } - public static final class HeartbeatInfo extends - com.google.protobuf.GeneratedMessage - implements HeartbeatInfoOrBuilder { - // Use HeartbeatInfo.newBuilder() to construct. - private HeartbeatInfo(Builder builder) { - super(builder); - } - private HeartbeatInfo(boolean noInit) {} - - private static final HeartbeatInfo defaultInstance; - public static HeartbeatInfo getDefaultInstance() { - return defaultInstance; - } - - public HeartbeatInfo getDefaultInstanceForType() { - return defaultInstance; - } - - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return com.alibaba.rocketmq.common.protocol.MQProtos.internal_static_rocketmq_HeartbeatInfo_descriptor; - } - - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return com.alibaba.rocketmq.common.protocol.MQProtos.internal_static_rocketmq_HeartbeatInfo_fieldAccessorTable; - } - - private int bitField0_; - // required string clientID = 1; - public static final int CLIENTID_FIELD_NUMBER = 1; - private java.lang.Object clientID_; - public boolean hasClientID() { - return ((bitField0_ & 0x00000001) == 0x00000001); - } - public String getClientID() { - java.lang.Object ref = clientID_; - if (ref instanceof String) { - return (String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - String s = bs.toStringUtf8(); - if (com.google.protobuf.Internal.isValidUtf8(bs)) { - clientID_ = s; - } - return s; - } - } - private com.google.protobuf.ByteString getClientIDBytes() { - java.lang.Object ref = clientID_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8((String) ref); - clientID_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - // repeated .rocketmq.ProducerInfo producerInfos = 2; - public static final int PRODUCERINFOS_FIELD_NUMBER = 2; - private java.util.List producerInfos_; - public java.util.List getProducerInfosList() { - return producerInfos_; - } - public java.util.List - getProducerInfosOrBuilderList() { - return producerInfos_; - } - public int getProducerInfosCount() { - return producerInfos_.size(); - } - public com.alibaba.rocketmq.common.protocol.MQProtos.ProducerInfo getProducerInfos(int index) { - return producerInfos_.get(index); - } - public com.alibaba.rocketmq.common.protocol.MQProtos.ProducerInfoOrBuilder getProducerInfosOrBuilder( - int index) { - return producerInfos_.get(index); - } - - // repeated .rocketmq.ConsumerInfo consumerInfos = 3; - public static final int CONSUMERINFOS_FIELD_NUMBER = 3; - private java.util.List consumerInfos_; - public java.util.List getConsumerInfosList() { - return consumerInfos_; - } - public java.util.List - getConsumerInfosOrBuilderList() { - return consumerInfos_; - } - public int getConsumerInfosCount() { - return consumerInfos_.size(); - } - public com.alibaba.rocketmq.common.protocol.MQProtos.ConsumerInfo getConsumerInfos(int index) { - return consumerInfos_.get(index); - } - public com.alibaba.rocketmq.common.protocol.MQProtos.ConsumerInfoOrBuilder getConsumerInfosOrBuilder( - int index) { - return consumerInfos_.get(index); - } - - private void initFields() { - clientID_ = ""; - producerInfos_ = java.util.Collections.emptyList(); - consumerInfos_ = java.util.Collections.emptyList(); - } - private byte memoizedIsInitialized = -1; - public final boolean isInitialized() { - byte isInitialized = memoizedIsInitialized; - if (isInitialized != -1) return isInitialized == 1; - - if (!hasClientID()) { - memoizedIsInitialized = 0; - return false; - } - for (int i = 0; i < getProducerInfosCount(); i++) { - if (!getProducerInfos(i).isInitialized()) { - memoizedIsInitialized = 0; - return false; - } - } - for (int i = 0; i < getConsumerInfosCount(); i++) { - if (!getConsumerInfos(i).isInitialized()) { - memoizedIsInitialized = 0; - return false; - } - } - memoizedIsInitialized = 1; - return true; - } - - public void writeTo(com.google.protobuf.CodedOutputStream output) - throws java.io.IOException { - getSerializedSize(); - if (((bitField0_ & 0x00000001) == 0x00000001)) { - output.writeBytes(1, getClientIDBytes()); - } - for (int i = 0; i < producerInfos_.size(); i++) { - output.writeMessage(2, producerInfos_.get(i)); - } - for (int i = 0; i < consumerInfos_.size(); i++) { - output.writeMessage(3, consumerInfos_.get(i)); - } - getUnknownFields().writeTo(output); - } - - private int memoizedSerializedSize = -1; - public int getSerializedSize() { - int size = memoizedSerializedSize; - if (size != -1) return size; - - size = 0; - if (((bitField0_ & 0x00000001) == 0x00000001)) { - size += com.google.protobuf.CodedOutputStream - .computeBytesSize(1, getClientIDBytes()); - } - for (int i = 0; i < producerInfos_.size(); i++) { - size += com.google.protobuf.CodedOutputStream - .computeMessageSize(2, producerInfos_.get(i)); - } - for (int i = 0; i < consumerInfos_.size(); i++) { - size += com.google.protobuf.CodedOutputStream - .computeMessageSize(3, consumerInfos_.get(i)); - } - size += getUnknownFields().getSerializedSize(); - memoizedSerializedSize = size; - return size; - } - - private static final long serialVersionUID = 0L; - @java.lang.Override - protected java.lang.Object writeReplace() - throws java.io.ObjectStreamException { - return super.writeReplace(); - } - - public static com.alibaba.rocketmq.common.protocol.MQProtos.HeartbeatInfo parseFrom( - com.google.protobuf.ByteString data) - throws com.google.protobuf.InvalidProtocolBufferException { - return newBuilder().mergeFrom(data).buildParsed(); - } - public static com.alibaba.rocketmq.common.protocol.MQProtos.HeartbeatInfo parseFrom( - com.google.protobuf.ByteString data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return newBuilder().mergeFrom(data, extensionRegistry) - .buildParsed(); - } - public static com.alibaba.rocketmq.common.protocol.MQProtos.HeartbeatInfo parseFrom(byte[] data) - throws com.google.protobuf.InvalidProtocolBufferException { - return newBuilder().mergeFrom(data).buildParsed(); - } - public static com.alibaba.rocketmq.common.protocol.MQProtos.HeartbeatInfo parseFrom( - byte[] data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return newBuilder().mergeFrom(data, extensionRegistry) - .buildParsed(); - } - public static com.alibaba.rocketmq.common.protocol.MQProtos.HeartbeatInfo parseFrom(java.io.InputStream input) - throws java.io.IOException { - return newBuilder().mergeFrom(input).buildParsed(); - } - public static com.alibaba.rocketmq.common.protocol.MQProtos.HeartbeatInfo parseFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return newBuilder().mergeFrom(input, extensionRegistry) - .buildParsed(); - } - public static com.alibaba.rocketmq.common.protocol.MQProtos.HeartbeatInfo parseDelimitedFrom(java.io.InputStream input) - throws java.io.IOException { - Builder builder = newBuilder(); - if (builder.mergeDelimitedFrom(input)) { - return builder.buildParsed(); - } else { - return null; - } - } - public static com.alibaba.rocketmq.common.protocol.MQProtos.HeartbeatInfo parseDelimitedFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - Builder builder = newBuilder(); - if (builder.mergeDelimitedFrom(input, extensionRegistry)) { - return builder.buildParsed(); - } else { - return null; - } - } - public static com.alibaba.rocketmq.common.protocol.MQProtos.HeartbeatInfo parseFrom( - com.google.protobuf.CodedInputStream input) - throws java.io.IOException { - return newBuilder().mergeFrom(input).buildParsed(); - } - public static com.alibaba.rocketmq.common.protocol.MQProtos.HeartbeatInfo parseFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return newBuilder().mergeFrom(input, extensionRegistry) - .buildParsed(); - } - - public static Builder newBuilder() { return Builder.create(); } - public Builder newBuilderForType() { return newBuilder(); } - public static Builder newBuilder(com.alibaba.rocketmq.common.protocol.MQProtos.HeartbeatInfo prototype) { - return newBuilder().mergeFrom(prototype); - } - public Builder toBuilder() { return newBuilder(this); } - - @java.lang.Override - protected Builder newBuilderForType( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - Builder builder = new Builder(parent); - return builder; - } - public static final class Builder extends - com.google.protobuf.GeneratedMessage.Builder - implements com.alibaba.rocketmq.common.protocol.MQProtos.HeartbeatInfoOrBuilder { - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return com.alibaba.rocketmq.common.protocol.MQProtos.internal_static_rocketmq_HeartbeatInfo_descriptor; - } - - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return com.alibaba.rocketmq.common.protocol.MQProtos.internal_static_rocketmq_HeartbeatInfo_fieldAccessorTable; - } - - // Construct using com.alibaba.rocketmq.common.protocol.MQProtos.HeartbeatInfo.newBuilder() - private Builder() { - maybeForceBuilderInitialization(); - } - - private Builder(BuilderParent parent) { - super(parent); - maybeForceBuilderInitialization(); - } - private void maybeForceBuilderInitialization() { - if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) { - getProducerInfosFieldBuilder(); - getConsumerInfosFieldBuilder(); - } - } - private static Builder create() { - return new Builder(); - } - - public Builder clear() { - super.clear(); - clientID_ = ""; - bitField0_ = (bitField0_ & ~0x00000001); - if (producerInfosBuilder_ == null) { - producerInfos_ = java.util.Collections.emptyList(); - bitField0_ = (bitField0_ & ~0x00000002); - } else { - producerInfosBuilder_.clear(); - } - if (consumerInfosBuilder_ == null) { - consumerInfos_ = java.util.Collections.emptyList(); - bitField0_ = (bitField0_ & ~0x00000004); - } else { - consumerInfosBuilder_.clear(); - } - return this; - } - - public Builder clone() { - return create().mergeFrom(buildPartial()); - } - - public com.google.protobuf.Descriptors.Descriptor - getDescriptorForType() { - return com.alibaba.rocketmq.common.protocol.MQProtos.HeartbeatInfo.getDescriptor(); - } - - public com.alibaba.rocketmq.common.protocol.MQProtos.HeartbeatInfo getDefaultInstanceForType() { - return com.alibaba.rocketmq.common.protocol.MQProtos.HeartbeatInfo.getDefaultInstance(); - } - - public com.alibaba.rocketmq.common.protocol.MQProtos.HeartbeatInfo build() { - com.alibaba.rocketmq.common.protocol.MQProtos.HeartbeatInfo result = buildPartial(); - if (!result.isInitialized()) { - throw newUninitializedMessageException(result); - } - return result; - } - - private com.alibaba.rocketmq.common.protocol.MQProtos.HeartbeatInfo buildParsed() - throws com.google.protobuf.InvalidProtocolBufferException { - com.alibaba.rocketmq.common.protocol.MQProtos.HeartbeatInfo result = buildPartial(); - if (!result.isInitialized()) { - throw newUninitializedMessageException( - result).asInvalidProtocolBufferException(); - } - return result; - } - - public com.alibaba.rocketmq.common.protocol.MQProtos.HeartbeatInfo buildPartial() { - com.alibaba.rocketmq.common.protocol.MQProtos.HeartbeatInfo result = new com.alibaba.rocketmq.common.protocol.MQProtos.HeartbeatInfo(this); - int from_bitField0_ = bitField0_; - int to_bitField0_ = 0; - if (((from_bitField0_ & 0x00000001) == 0x00000001)) { - to_bitField0_ |= 0x00000001; - } - result.clientID_ = clientID_; - if (producerInfosBuilder_ == null) { - if (((bitField0_ & 0x00000002) == 0x00000002)) { - producerInfos_ = java.util.Collections.unmodifiableList(producerInfos_); - bitField0_ = (bitField0_ & ~0x00000002); - } - result.producerInfos_ = producerInfos_; - } else { - result.producerInfos_ = producerInfosBuilder_.build(); - } - if (consumerInfosBuilder_ == null) { - if (((bitField0_ & 0x00000004) == 0x00000004)) { - consumerInfos_ = java.util.Collections.unmodifiableList(consumerInfos_); - bitField0_ = (bitField0_ & ~0x00000004); - } - result.consumerInfos_ = consumerInfos_; - } else { - result.consumerInfos_ = consumerInfosBuilder_.build(); - } - result.bitField0_ = to_bitField0_; - onBuilt(); - return result; - } - - public Builder mergeFrom(com.google.protobuf.Message other) { - if (other instanceof com.alibaba.rocketmq.common.protocol.MQProtos.HeartbeatInfo) { - return mergeFrom((com.alibaba.rocketmq.common.protocol.MQProtos.HeartbeatInfo)other); - } else { - super.mergeFrom(other); - return this; - } - } - - public Builder mergeFrom(com.alibaba.rocketmq.common.protocol.MQProtos.HeartbeatInfo other) { - if (other == com.alibaba.rocketmq.common.protocol.MQProtos.HeartbeatInfo.getDefaultInstance()) return this; - if (other.hasClientID()) { - setClientID(other.getClientID()); - } - if (producerInfosBuilder_ == null) { - if (!other.producerInfos_.isEmpty()) { - if (producerInfos_.isEmpty()) { - producerInfos_ = other.producerInfos_; - bitField0_ = (bitField0_ & ~0x00000002); - } else { - ensureProducerInfosIsMutable(); - producerInfos_.addAll(other.producerInfos_); - } - onChanged(); - } - } else { - if (!other.producerInfos_.isEmpty()) { - if (producerInfosBuilder_.isEmpty()) { - producerInfosBuilder_.dispose(); - producerInfosBuilder_ = null; - producerInfos_ = other.producerInfos_; - bitField0_ = (bitField0_ & ~0x00000002); - producerInfosBuilder_ = - com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders ? - getProducerInfosFieldBuilder() : null; - } else { - producerInfosBuilder_.addAllMessages(other.producerInfos_); - } - } - } - if (consumerInfosBuilder_ == null) { - if (!other.consumerInfos_.isEmpty()) { - if (consumerInfos_.isEmpty()) { - consumerInfos_ = other.consumerInfos_; - bitField0_ = (bitField0_ & ~0x00000004); - } else { - ensureConsumerInfosIsMutable(); - consumerInfos_.addAll(other.consumerInfos_); - } - onChanged(); - } - } else { - if (!other.consumerInfos_.isEmpty()) { - if (consumerInfosBuilder_.isEmpty()) { - consumerInfosBuilder_.dispose(); - consumerInfosBuilder_ = null; - consumerInfos_ = other.consumerInfos_; - bitField0_ = (bitField0_ & ~0x00000004); - consumerInfosBuilder_ = - com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders ? - getConsumerInfosFieldBuilder() : null; - } else { - consumerInfosBuilder_.addAllMessages(other.consumerInfos_); - } - } - } - this.mergeUnknownFields(other.getUnknownFields()); - return this; - } - - public final boolean isInitialized() { - if (!hasClientID()) { - - return false; - } - for (int i = 0; i < getProducerInfosCount(); i++) { - if (!getProducerInfos(i).isInitialized()) { - - return false; - } - } - for (int i = 0; i < getConsumerInfosCount(); i++) { - if (!getConsumerInfos(i).isInitialized()) { - - return false; - } - } - return true; - } - - public Builder mergeFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - com.google.protobuf.UnknownFieldSet.Builder unknownFields = - com.google.protobuf.UnknownFieldSet.newBuilder( - this.getUnknownFields()); - while (true) { - int tag = input.readTag(); - switch (tag) { - case 0: - this.setUnknownFields(unknownFields.build()); - onChanged(); - return this; - default: { - if (!parseUnknownField(input, unknownFields, - extensionRegistry, tag)) { - this.setUnknownFields(unknownFields.build()); - onChanged(); - return this; - } - break; - } - case 10: { - bitField0_ |= 0x00000001; - clientID_ = input.readBytes(); - break; - } - case 18: { - com.alibaba.rocketmq.common.protocol.MQProtos.ProducerInfo.Builder subBuilder = com.alibaba.rocketmq.common.protocol.MQProtos.ProducerInfo.newBuilder(); - input.readMessage(subBuilder, extensionRegistry); - addProducerInfos(subBuilder.buildPartial()); - break; - } - case 26: { - com.alibaba.rocketmq.common.protocol.MQProtos.ConsumerInfo.Builder subBuilder = com.alibaba.rocketmq.common.protocol.MQProtos.ConsumerInfo.newBuilder(); - input.readMessage(subBuilder, extensionRegistry); - addConsumerInfos(subBuilder.buildPartial()); - break; - } - } - } - } - - private int bitField0_; - - // required string clientID = 1; - private java.lang.Object clientID_ = ""; - public boolean hasClientID() { - return ((bitField0_ & 0x00000001) == 0x00000001); - } - public String getClientID() { - java.lang.Object ref = clientID_; - if (!(ref instanceof String)) { - String s = ((com.google.protobuf.ByteString) ref).toStringUtf8(); - clientID_ = s; - return s; - } else { - return (String) ref; - } - } - public Builder setClientID(String value) { - if (value == null) { - throw new NullPointerException(); - } - bitField0_ |= 0x00000001; - clientID_ = value; - onChanged(); - return this; - } - public Builder clearClientID() { - bitField0_ = (bitField0_ & ~0x00000001); - clientID_ = getDefaultInstance().getClientID(); - onChanged(); - return this; - } - void setClientID(com.google.protobuf.ByteString value) { - bitField0_ |= 0x00000001; - clientID_ = value; - onChanged(); - } - - // repeated .rocketmq.ProducerInfo producerInfos = 2; - private java.util.List producerInfos_ = - java.util.Collections.emptyList(); - private void ensureProducerInfosIsMutable() { - if (!((bitField0_ & 0x00000002) == 0x00000002)) { - producerInfos_ = new java.util.ArrayList(producerInfos_); - bitField0_ |= 0x00000002; - } - } - - private com.google.protobuf.RepeatedFieldBuilder< - com.alibaba.rocketmq.common.protocol.MQProtos.ProducerInfo, com.alibaba.rocketmq.common.protocol.MQProtos.ProducerInfo.Builder, com.alibaba.rocketmq.common.protocol.MQProtos.ProducerInfoOrBuilder> producerInfosBuilder_; - - public java.util.List getProducerInfosList() { - if (producerInfosBuilder_ == null) { - return java.util.Collections.unmodifiableList(producerInfos_); - } else { - return producerInfosBuilder_.getMessageList(); - } - } - public int getProducerInfosCount() { - if (producerInfosBuilder_ == null) { - return producerInfos_.size(); - } else { - return producerInfosBuilder_.getCount(); - } - } - public com.alibaba.rocketmq.common.protocol.MQProtos.ProducerInfo getProducerInfos(int index) { - if (producerInfosBuilder_ == null) { - return producerInfos_.get(index); - } else { - return producerInfosBuilder_.getMessage(index); - } - } - public Builder setProducerInfos( - int index, com.alibaba.rocketmq.common.protocol.MQProtos.ProducerInfo value) { - if (producerInfosBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - ensureProducerInfosIsMutable(); - producerInfos_.set(index, value); - onChanged(); - } else { - producerInfosBuilder_.setMessage(index, value); - } - return this; - } - public Builder setProducerInfos( - int index, com.alibaba.rocketmq.common.protocol.MQProtos.ProducerInfo.Builder builderForValue) { - if (producerInfosBuilder_ == null) { - ensureProducerInfosIsMutable(); - producerInfos_.set(index, builderForValue.build()); - onChanged(); - } else { - producerInfosBuilder_.setMessage(index, builderForValue.build()); - } - return this; - } - public Builder addProducerInfos(com.alibaba.rocketmq.common.protocol.MQProtos.ProducerInfo value) { - if (producerInfosBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - ensureProducerInfosIsMutable(); - producerInfos_.add(value); - onChanged(); - } else { - producerInfosBuilder_.addMessage(value); - } - return this; - } - public Builder addProducerInfos( - int index, com.alibaba.rocketmq.common.protocol.MQProtos.ProducerInfo value) { - if (producerInfosBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - ensureProducerInfosIsMutable(); - producerInfos_.add(index, value); - onChanged(); - } else { - producerInfosBuilder_.addMessage(index, value); - } - return this; - } - public Builder addProducerInfos( - com.alibaba.rocketmq.common.protocol.MQProtos.ProducerInfo.Builder builderForValue) { - if (producerInfosBuilder_ == null) { - ensureProducerInfosIsMutable(); - producerInfos_.add(builderForValue.build()); - onChanged(); - } else { - producerInfosBuilder_.addMessage(builderForValue.build()); - } - return this; - } - public Builder addProducerInfos( - int index, com.alibaba.rocketmq.common.protocol.MQProtos.ProducerInfo.Builder builderForValue) { - if (producerInfosBuilder_ == null) { - ensureProducerInfosIsMutable(); - producerInfos_.add(index, builderForValue.build()); - onChanged(); - } else { - producerInfosBuilder_.addMessage(index, builderForValue.build()); - } - return this; - } - public Builder addAllProducerInfos( - java.lang.Iterable values) { - if (producerInfosBuilder_ == null) { - ensureProducerInfosIsMutable(); - super.addAll(values, producerInfos_); - onChanged(); - } else { - producerInfosBuilder_.addAllMessages(values); - } - return this; - } - public Builder clearProducerInfos() { - if (producerInfosBuilder_ == null) { - producerInfos_ = java.util.Collections.emptyList(); - bitField0_ = (bitField0_ & ~0x00000002); - onChanged(); - } else { - producerInfosBuilder_.clear(); - } - return this; - } - public Builder removeProducerInfos(int index) { - if (producerInfosBuilder_ == null) { - ensureProducerInfosIsMutable(); - producerInfos_.remove(index); - onChanged(); - } else { - producerInfosBuilder_.remove(index); - } - return this; - } - public com.alibaba.rocketmq.common.protocol.MQProtos.ProducerInfo.Builder getProducerInfosBuilder( - int index) { - return getProducerInfosFieldBuilder().getBuilder(index); - } - public com.alibaba.rocketmq.common.protocol.MQProtos.ProducerInfoOrBuilder getProducerInfosOrBuilder( - int index) { - if (producerInfosBuilder_ == null) { - return producerInfos_.get(index); } else { - return producerInfosBuilder_.getMessageOrBuilder(index); - } - } - public java.util.List - getProducerInfosOrBuilderList() { - if (producerInfosBuilder_ != null) { - return producerInfosBuilder_.getMessageOrBuilderList(); - } else { - return java.util.Collections.unmodifiableList(producerInfos_); - } - } - public com.alibaba.rocketmq.common.protocol.MQProtos.ProducerInfo.Builder addProducerInfosBuilder() { - return getProducerInfosFieldBuilder().addBuilder( - com.alibaba.rocketmq.common.protocol.MQProtos.ProducerInfo.getDefaultInstance()); - } - public com.alibaba.rocketmq.common.protocol.MQProtos.ProducerInfo.Builder addProducerInfosBuilder( - int index) { - return getProducerInfosFieldBuilder().addBuilder( - index, com.alibaba.rocketmq.common.protocol.MQProtos.ProducerInfo.getDefaultInstance()); - } - public java.util.List - getProducerInfosBuilderList() { - return getProducerInfosFieldBuilder().getBuilderList(); - } - private com.google.protobuf.RepeatedFieldBuilder< - com.alibaba.rocketmq.common.protocol.MQProtos.ProducerInfo, com.alibaba.rocketmq.common.protocol.MQProtos.ProducerInfo.Builder, com.alibaba.rocketmq.common.protocol.MQProtos.ProducerInfoOrBuilder> - getProducerInfosFieldBuilder() { - if (producerInfosBuilder_ == null) { - producerInfosBuilder_ = new com.google.protobuf.RepeatedFieldBuilder< - com.alibaba.rocketmq.common.protocol.MQProtos.ProducerInfo, com.alibaba.rocketmq.common.protocol.MQProtos.ProducerInfo.Builder, com.alibaba.rocketmq.common.protocol.MQProtos.ProducerInfoOrBuilder>( - producerInfos_, - ((bitField0_ & 0x00000002) == 0x00000002), - getParentForChildren(), - isClean()); - producerInfos_ = null; - } - return producerInfosBuilder_; - } - - // repeated .rocketmq.ConsumerInfo consumerInfos = 3; - private java.util.List consumerInfos_ = - java.util.Collections.emptyList(); - private void ensureConsumerInfosIsMutable() { - if (!((bitField0_ & 0x00000004) == 0x00000004)) { - consumerInfos_ = new java.util.ArrayList(consumerInfos_); - bitField0_ |= 0x00000004; - } - } - - private com.google.protobuf.RepeatedFieldBuilder< - com.alibaba.rocketmq.common.protocol.MQProtos.ConsumerInfo, com.alibaba.rocketmq.common.protocol.MQProtos.ConsumerInfo.Builder, com.alibaba.rocketmq.common.protocol.MQProtos.ConsumerInfoOrBuilder> consumerInfosBuilder_; - - public java.util.List getConsumerInfosList() { - if (consumerInfosBuilder_ == null) { - return java.util.Collections.unmodifiableList(consumerInfos_); - } else { - return consumerInfosBuilder_.getMessageList(); - } - } - public int getConsumerInfosCount() { - if (consumerInfosBuilder_ == null) { - return consumerInfos_.size(); - } else { - return consumerInfosBuilder_.getCount(); - } - } - public com.alibaba.rocketmq.common.protocol.MQProtos.ConsumerInfo getConsumerInfos(int index) { - if (consumerInfosBuilder_ == null) { - return consumerInfos_.get(index); - } else { - return consumerInfosBuilder_.getMessage(index); - } - } - public Builder setConsumerInfos( - int index, com.alibaba.rocketmq.common.protocol.MQProtos.ConsumerInfo value) { - if (consumerInfosBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - ensureConsumerInfosIsMutable(); - consumerInfos_.set(index, value); - onChanged(); - } else { - consumerInfosBuilder_.setMessage(index, value); - } - return this; - } - public Builder setConsumerInfos( - int index, com.alibaba.rocketmq.common.protocol.MQProtos.ConsumerInfo.Builder builderForValue) { - if (consumerInfosBuilder_ == null) { - ensureConsumerInfosIsMutable(); - consumerInfos_.set(index, builderForValue.build()); - onChanged(); - } else { - consumerInfosBuilder_.setMessage(index, builderForValue.build()); - } - return this; - } - public Builder addConsumerInfos(com.alibaba.rocketmq.common.protocol.MQProtos.ConsumerInfo value) { - if (consumerInfosBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - ensureConsumerInfosIsMutable(); - consumerInfos_.add(value); - onChanged(); - } else { - consumerInfosBuilder_.addMessage(value); - } - return this; - } - public Builder addConsumerInfos( - int index, com.alibaba.rocketmq.common.protocol.MQProtos.ConsumerInfo value) { - if (consumerInfosBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - ensureConsumerInfosIsMutable(); - consumerInfos_.add(index, value); - onChanged(); - } else { - consumerInfosBuilder_.addMessage(index, value); - } - return this; - } - public Builder addConsumerInfos( - com.alibaba.rocketmq.common.protocol.MQProtos.ConsumerInfo.Builder builderForValue) { - if (consumerInfosBuilder_ == null) { - ensureConsumerInfosIsMutable(); - consumerInfos_.add(builderForValue.build()); - onChanged(); - } else { - consumerInfosBuilder_.addMessage(builderForValue.build()); - } - return this; - } - public Builder addConsumerInfos( - int index, com.alibaba.rocketmq.common.protocol.MQProtos.ConsumerInfo.Builder builderForValue) { - if (consumerInfosBuilder_ == null) { - ensureConsumerInfosIsMutable(); - consumerInfos_.add(index, builderForValue.build()); - onChanged(); - } else { - consumerInfosBuilder_.addMessage(index, builderForValue.build()); - } - return this; - } - public Builder addAllConsumerInfos( - java.lang.Iterable values) { - if (consumerInfosBuilder_ == null) { - ensureConsumerInfosIsMutable(); - super.addAll(values, consumerInfos_); - onChanged(); - } else { - consumerInfosBuilder_.addAllMessages(values); - } - return this; - } - public Builder clearConsumerInfos() { - if (consumerInfosBuilder_ == null) { - consumerInfos_ = java.util.Collections.emptyList(); - bitField0_ = (bitField0_ & ~0x00000004); - onChanged(); - } else { - consumerInfosBuilder_.clear(); - } - return this; - } - public Builder removeConsumerInfos(int index) { - if (consumerInfosBuilder_ == null) { - ensureConsumerInfosIsMutable(); - consumerInfos_.remove(index); - onChanged(); - } else { - consumerInfosBuilder_.remove(index); - } - return this; - } - public com.alibaba.rocketmq.common.protocol.MQProtos.ConsumerInfo.Builder getConsumerInfosBuilder( - int index) { - return getConsumerInfosFieldBuilder().getBuilder(index); - } - public com.alibaba.rocketmq.common.protocol.MQProtos.ConsumerInfoOrBuilder getConsumerInfosOrBuilder( - int index) { - if (consumerInfosBuilder_ == null) { - return consumerInfos_.get(index); } else { - return consumerInfosBuilder_.getMessageOrBuilder(index); - } - } - public java.util.List - getConsumerInfosOrBuilderList() { - if (consumerInfosBuilder_ != null) { - return consumerInfosBuilder_.getMessageOrBuilderList(); - } else { - return java.util.Collections.unmodifiableList(consumerInfos_); - } - } - public com.alibaba.rocketmq.common.protocol.MQProtos.ConsumerInfo.Builder addConsumerInfosBuilder() { - return getConsumerInfosFieldBuilder().addBuilder( - com.alibaba.rocketmq.common.protocol.MQProtos.ConsumerInfo.getDefaultInstance()); - } - public com.alibaba.rocketmq.common.protocol.MQProtos.ConsumerInfo.Builder addConsumerInfosBuilder( - int index) { - return getConsumerInfosFieldBuilder().addBuilder( - index, com.alibaba.rocketmq.common.protocol.MQProtos.ConsumerInfo.getDefaultInstance()); - } - public java.util.List - getConsumerInfosBuilderList() { - return getConsumerInfosFieldBuilder().getBuilderList(); - } - private com.google.protobuf.RepeatedFieldBuilder< - com.alibaba.rocketmq.common.protocol.MQProtos.ConsumerInfo, com.alibaba.rocketmq.common.protocol.MQProtos.ConsumerInfo.Builder, com.alibaba.rocketmq.common.protocol.MQProtos.ConsumerInfoOrBuilder> - getConsumerInfosFieldBuilder() { - if (consumerInfosBuilder_ == null) { - consumerInfosBuilder_ = new com.google.protobuf.RepeatedFieldBuilder< - com.alibaba.rocketmq.common.protocol.MQProtos.ConsumerInfo, com.alibaba.rocketmq.common.protocol.MQProtos.ConsumerInfo.Builder, com.alibaba.rocketmq.common.protocol.MQProtos.ConsumerInfoOrBuilder>( - consumerInfos_, - ((bitField0_ & 0x00000004) == 0x00000004), - getParentForChildren(), - isClean()); - consumerInfos_ = null; - } - return consumerInfosBuilder_; - } - - // @@protoc_insertion_point(builder_scope:rocketmq.HeartbeatInfo) - } - - static { - defaultInstance = new HeartbeatInfo(true); - defaultInstance.initFields(); - } - - // @@protoc_insertion_point(class_scope:rocketmq.HeartbeatInfo) - } - - public interface TopicQueuePairOrBuilder - extends com.google.protobuf.MessageOrBuilder { - - // required string topic = 1; - boolean hasTopic(); - String getTopic(); - - // repeated .rocketmq.QueueInfo queueInfo = 2; - java.util.List - getQueueInfoList(); - com.alibaba.rocketmq.common.protocol.MQProtos.QueueInfo getQueueInfo(int index); - int getQueueInfoCount(); - java.util.List - getQueueInfoOrBuilderList(); - com.alibaba.rocketmq.common.protocol.MQProtos.QueueInfoOrBuilder getQueueInfoOrBuilder( - int index); - } - public static final class TopicQueuePair extends - com.google.protobuf.GeneratedMessage - implements TopicQueuePairOrBuilder { - // Use TopicQueuePair.newBuilder() to construct. - private TopicQueuePair(Builder builder) { - super(builder); - } - private TopicQueuePair(boolean noInit) {} - - private static final TopicQueuePair defaultInstance; - public static TopicQueuePair getDefaultInstance() { - return defaultInstance; - } - - public TopicQueuePair getDefaultInstanceForType() { - return defaultInstance; - } - - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return com.alibaba.rocketmq.common.protocol.MQProtos.internal_static_rocketmq_TopicQueuePair_descriptor; - } - - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return com.alibaba.rocketmq.common.protocol.MQProtos.internal_static_rocketmq_TopicQueuePair_fieldAccessorTable; - } - - private int bitField0_; - // required string topic = 1; - public static final int TOPIC_FIELD_NUMBER = 1; - private java.lang.Object topic_; - public boolean hasTopic() { - return ((bitField0_ & 0x00000001) == 0x00000001); - } - public String getTopic() { - java.lang.Object ref = topic_; - if (ref instanceof String) { - return (String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - String s = bs.toStringUtf8(); - if (com.google.protobuf.Internal.isValidUtf8(bs)) { - topic_ = s; - } - return s; - } - } - private com.google.protobuf.ByteString getTopicBytes() { - java.lang.Object ref = topic_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8((String) ref); - topic_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - // repeated .rocketmq.QueueInfo queueInfo = 2; - public static final int QUEUEINFO_FIELD_NUMBER = 2; - private java.util.List queueInfo_; - public java.util.List getQueueInfoList() { - return queueInfo_; - } - public java.util.List - getQueueInfoOrBuilderList() { - return queueInfo_; - } - public int getQueueInfoCount() { - return queueInfo_.size(); - } - public com.alibaba.rocketmq.common.protocol.MQProtos.QueueInfo getQueueInfo(int index) { - return queueInfo_.get(index); - } - public com.alibaba.rocketmq.common.protocol.MQProtos.QueueInfoOrBuilder getQueueInfoOrBuilder( - int index) { - return queueInfo_.get(index); - } - - private void initFields() { - topic_ = ""; - queueInfo_ = java.util.Collections.emptyList(); - } - private byte memoizedIsInitialized = -1; - public final boolean isInitialized() { - byte isInitialized = memoizedIsInitialized; - if (isInitialized != -1) return isInitialized == 1; - - if (!hasTopic()) { - memoizedIsInitialized = 0; - return false; - } - for (int i = 0; i < getQueueInfoCount(); i++) { - if (!getQueueInfo(i).isInitialized()) { - memoizedIsInitialized = 0; - return false; - } - } - memoizedIsInitialized = 1; - return true; - } - - public void writeTo(com.google.protobuf.CodedOutputStream output) - throws java.io.IOException { - getSerializedSize(); - if (((bitField0_ & 0x00000001) == 0x00000001)) { - output.writeBytes(1, getTopicBytes()); - } - for (int i = 0; i < queueInfo_.size(); i++) { - output.writeMessage(2, queueInfo_.get(i)); - } - getUnknownFields().writeTo(output); - } - - private int memoizedSerializedSize = -1; - public int getSerializedSize() { - int size = memoizedSerializedSize; - if (size != -1) return size; - - size = 0; - if (((bitField0_ & 0x00000001) == 0x00000001)) { - size += com.google.protobuf.CodedOutputStream - .computeBytesSize(1, getTopicBytes()); - } - for (int i = 0; i < queueInfo_.size(); i++) { - size += com.google.protobuf.CodedOutputStream - .computeMessageSize(2, queueInfo_.get(i)); - } - size += getUnknownFields().getSerializedSize(); - memoizedSerializedSize = size; - return size; - } - - private static final long serialVersionUID = 0L; - @java.lang.Override - protected java.lang.Object writeReplace() - throws java.io.ObjectStreamException { - return super.writeReplace(); - } - - public static com.alibaba.rocketmq.common.protocol.MQProtos.TopicQueuePair parseFrom( - com.google.protobuf.ByteString data) - throws com.google.protobuf.InvalidProtocolBufferException { - return newBuilder().mergeFrom(data).buildParsed(); - } - public static com.alibaba.rocketmq.common.protocol.MQProtos.TopicQueuePair parseFrom( - com.google.protobuf.ByteString data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return newBuilder().mergeFrom(data, extensionRegistry) - .buildParsed(); - } - public static com.alibaba.rocketmq.common.protocol.MQProtos.TopicQueuePair parseFrom(byte[] data) - throws com.google.protobuf.InvalidProtocolBufferException { - return newBuilder().mergeFrom(data).buildParsed(); - } - public static com.alibaba.rocketmq.common.protocol.MQProtos.TopicQueuePair parseFrom( - byte[] data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return newBuilder().mergeFrom(data, extensionRegistry) - .buildParsed(); - } - public static com.alibaba.rocketmq.common.protocol.MQProtos.TopicQueuePair parseFrom(java.io.InputStream input) - throws java.io.IOException { - return newBuilder().mergeFrom(input).buildParsed(); - } - public static com.alibaba.rocketmq.common.protocol.MQProtos.TopicQueuePair parseFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return newBuilder().mergeFrom(input, extensionRegistry) - .buildParsed(); - } - public static com.alibaba.rocketmq.common.protocol.MQProtos.TopicQueuePair parseDelimitedFrom(java.io.InputStream input) - throws java.io.IOException { - Builder builder = newBuilder(); - if (builder.mergeDelimitedFrom(input)) { - return builder.buildParsed(); - } else { - return null; - } - } - public static com.alibaba.rocketmq.common.protocol.MQProtos.TopicQueuePair parseDelimitedFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - Builder builder = newBuilder(); - if (builder.mergeDelimitedFrom(input, extensionRegistry)) { - return builder.buildParsed(); - } else { - return null; - } - } - public static com.alibaba.rocketmq.common.protocol.MQProtos.TopicQueuePair parseFrom( - com.google.protobuf.CodedInputStream input) - throws java.io.IOException { - return newBuilder().mergeFrom(input).buildParsed(); - } - public static com.alibaba.rocketmq.common.protocol.MQProtos.TopicQueuePair parseFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return newBuilder().mergeFrom(input, extensionRegistry) - .buildParsed(); - } - - public static Builder newBuilder() { return Builder.create(); } - public Builder newBuilderForType() { return newBuilder(); } - public static Builder newBuilder(com.alibaba.rocketmq.common.protocol.MQProtos.TopicQueuePair prototype) { - return newBuilder().mergeFrom(prototype); - } - public Builder toBuilder() { return newBuilder(this); } - - @java.lang.Override - protected Builder newBuilderForType( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - Builder builder = new Builder(parent); - return builder; - } - public static final class Builder extends - com.google.protobuf.GeneratedMessage.Builder - implements com.alibaba.rocketmq.common.protocol.MQProtos.TopicQueuePairOrBuilder { - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return com.alibaba.rocketmq.common.protocol.MQProtos.internal_static_rocketmq_TopicQueuePair_descriptor; - } - - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return com.alibaba.rocketmq.common.protocol.MQProtos.internal_static_rocketmq_TopicQueuePair_fieldAccessorTable; - } - - // Construct using com.alibaba.rocketmq.common.protocol.MQProtos.TopicQueuePair.newBuilder() - private Builder() { - maybeForceBuilderInitialization(); - } - - private Builder(BuilderParent parent) { - super(parent); - maybeForceBuilderInitialization(); - } - private void maybeForceBuilderInitialization() { - if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) { - getQueueInfoFieldBuilder(); - } - } - private static Builder create() { - return new Builder(); - } - - public Builder clear() { - super.clear(); - topic_ = ""; - bitField0_ = (bitField0_ & ~0x00000001); - if (queueInfoBuilder_ == null) { - queueInfo_ = java.util.Collections.emptyList(); - bitField0_ = (bitField0_ & ~0x00000002); - } else { - queueInfoBuilder_.clear(); - } - return this; - } - - public Builder clone() { - return create().mergeFrom(buildPartial()); - } - - public com.google.protobuf.Descriptors.Descriptor - getDescriptorForType() { - return com.alibaba.rocketmq.common.protocol.MQProtos.TopicQueuePair.getDescriptor(); - } - - public com.alibaba.rocketmq.common.protocol.MQProtos.TopicQueuePair getDefaultInstanceForType() { - return com.alibaba.rocketmq.common.protocol.MQProtos.TopicQueuePair.getDefaultInstance(); - } - - public com.alibaba.rocketmq.common.protocol.MQProtos.TopicQueuePair build() { - com.alibaba.rocketmq.common.protocol.MQProtos.TopicQueuePair result = buildPartial(); - if (!result.isInitialized()) { - throw newUninitializedMessageException(result); - } - return result; - } - - private com.alibaba.rocketmq.common.protocol.MQProtos.TopicQueuePair buildParsed() - throws com.google.protobuf.InvalidProtocolBufferException { - com.alibaba.rocketmq.common.protocol.MQProtos.TopicQueuePair result = buildPartial(); - if (!result.isInitialized()) { - throw newUninitializedMessageException( - result).asInvalidProtocolBufferException(); - } - return result; - } - - public com.alibaba.rocketmq.common.protocol.MQProtos.TopicQueuePair buildPartial() { - com.alibaba.rocketmq.common.protocol.MQProtos.TopicQueuePair result = new com.alibaba.rocketmq.common.protocol.MQProtos.TopicQueuePair(this); - int from_bitField0_ = bitField0_; - int to_bitField0_ = 0; - if (((from_bitField0_ & 0x00000001) == 0x00000001)) { - to_bitField0_ |= 0x00000001; - } - result.topic_ = topic_; - if (queueInfoBuilder_ == null) { - if (((bitField0_ & 0x00000002) == 0x00000002)) { - queueInfo_ = java.util.Collections.unmodifiableList(queueInfo_); - bitField0_ = (bitField0_ & ~0x00000002); - } - result.queueInfo_ = queueInfo_; - } else { - result.queueInfo_ = queueInfoBuilder_.build(); - } - result.bitField0_ = to_bitField0_; - onBuilt(); - return result; - } - - public Builder mergeFrom(com.google.protobuf.Message other) { - if (other instanceof com.alibaba.rocketmq.common.protocol.MQProtos.TopicQueuePair) { - return mergeFrom((com.alibaba.rocketmq.common.protocol.MQProtos.TopicQueuePair)other); - } else { - super.mergeFrom(other); - return this; - } - } - - public Builder mergeFrom(com.alibaba.rocketmq.common.protocol.MQProtos.TopicQueuePair other) { - if (other == com.alibaba.rocketmq.common.protocol.MQProtos.TopicQueuePair.getDefaultInstance()) return this; - if (other.hasTopic()) { - setTopic(other.getTopic()); - } - if (queueInfoBuilder_ == null) { - if (!other.queueInfo_.isEmpty()) { - if (queueInfo_.isEmpty()) { - queueInfo_ = other.queueInfo_; - bitField0_ = (bitField0_ & ~0x00000002); - } else { - ensureQueueInfoIsMutable(); - queueInfo_.addAll(other.queueInfo_); - } - onChanged(); - } - } else { - if (!other.queueInfo_.isEmpty()) { - if (queueInfoBuilder_.isEmpty()) { - queueInfoBuilder_.dispose(); - queueInfoBuilder_ = null; - queueInfo_ = other.queueInfo_; - bitField0_ = (bitField0_ & ~0x00000002); - queueInfoBuilder_ = - com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders ? - getQueueInfoFieldBuilder() : null; - } else { - queueInfoBuilder_.addAllMessages(other.queueInfo_); - } - } - } - this.mergeUnknownFields(other.getUnknownFields()); - return this; - } - - public final boolean isInitialized() { - if (!hasTopic()) { - - return false; - } - for (int i = 0; i < getQueueInfoCount(); i++) { - if (!getQueueInfo(i).isInitialized()) { - - return false; - } - } - return true; - } - - public Builder mergeFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - com.google.protobuf.UnknownFieldSet.Builder unknownFields = - com.google.protobuf.UnknownFieldSet.newBuilder( - this.getUnknownFields()); - while (true) { - int tag = input.readTag(); - switch (tag) { - case 0: - this.setUnknownFields(unknownFields.build()); - onChanged(); - return this; - default: { - if (!parseUnknownField(input, unknownFields, - extensionRegistry, tag)) { - this.setUnknownFields(unknownFields.build()); - onChanged(); - return this; - } - break; - } - case 10: { - bitField0_ |= 0x00000001; - topic_ = input.readBytes(); - break; - } - case 18: { - com.alibaba.rocketmq.common.protocol.MQProtos.QueueInfo.Builder subBuilder = com.alibaba.rocketmq.common.protocol.MQProtos.QueueInfo.newBuilder(); - input.readMessage(subBuilder, extensionRegistry); - addQueueInfo(subBuilder.buildPartial()); - break; - } - } - } - } - - private int bitField0_; - - // required string topic = 1; - private java.lang.Object topic_ = ""; - public boolean hasTopic() { - return ((bitField0_ & 0x00000001) == 0x00000001); - } - public String getTopic() { - java.lang.Object ref = topic_; - if (!(ref instanceof String)) { - String s = ((com.google.protobuf.ByteString) ref).toStringUtf8(); - topic_ = s; - return s; - } else { - return (String) ref; - } - } - public Builder setTopic(String value) { - if (value == null) { - throw new NullPointerException(); - } - bitField0_ |= 0x00000001; - topic_ = value; - onChanged(); - return this; - } - public Builder clearTopic() { - bitField0_ = (bitField0_ & ~0x00000001); - topic_ = getDefaultInstance().getTopic(); - onChanged(); - return this; - } - void setTopic(com.google.protobuf.ByteString value) { - bitField0_ |= 0x00000001; - topic_ = value; - onChanged(); - } - - // repeated .rocketmq.QueueInfo queueInfo = 2; - private java.util.List queueInfo_ = - java.util.Collections.emptyList(); - private void ensureQueueInfoIsMutable() { - if (!((bitField0_ & 0x00000002) == 0x00000002)) { - queueInfo_ = new java.util.ArrayList(queueInfo_); - bitField0_ |= 0x00000002; - } - } - - private com.google.protobuf.RepeatedFieldBuilder< - com.alibaba.rocketmq.common.protocol.MQProtos.QueueInfo, com.alibaba.rocketmq.common.protocol.MQProtos.QueueInfo.Builder, com.alibaba.rocketmq.common.protocol.MQProtos.QueueInfoOrBuilder> queueInfoBuilder_; - - public java.util.List getQueueInfoList() { - if (queueInfoBuilder_ == null) { - return java.util.Collections.unmodifiableList(queueInfo_); - } else { - return queueInfoBuilder_.getMessageList(); - } - } - public int getQueueInfoCount() { - if (queueInfoBuilder_ == null) { - return queueInfo_.size(); - } else { - return queueInfoBuilder_.getCount(); - } - } - public com.alibaba.rocketmq.common.protocol.MQProtos.QueueInfo getQueueInfo(int index) { - if (queueInfoBuilder_ == null) { - return queueInfo_.get(index); - } else { - return queueInfoBuilder_.getMessage(index); - } - } - public Builder setQueueInfo( - int index, com.alibaba.rocketmq.common.protocol.MQProtos.QueueInfo value) { - if (queueInfoBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - ensureQueueInfoIsMutable(); - queueInfo_.set(index, value); - onChanged(); - } else { - queueInfoBuilder_.setMessage(index, value); - } - return this; - } - public Builder setQueueInfo( - int index, com.alibaba.rocketmq.common.protocol.MQProtos.QueueInfo.Builder builderForValue) { - if (queueInfoBuilder_ == null) { - ensureQueueInfoIsMutable(); - queueInfo_.set(index, builderForValue.build()); - onChanged(); - } else { - queueInfoBuilder_.setMessage(index, builderForValue.build()); - } - return this; - } - public Builder addQueueInfo(com.alibaba.rocketmq.common.protocol.MQProtos.QueueInfo value) { - if (queueInfoBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - ensureQueueInfoIsMutable(); - queueInfo_.add(value); - onChanged(); - } else { - queueInfoBuilder_.addMessage(value); - } - return this; - } - public Builder addQueueInfo( - int index, com.alibaba.rocketmq.common.protocol.MQProtos.QueueInfo value) { - if (queueInfoBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - ensureQueueInfoIsMutable(); - queueInfo_.add(index, value); - onChanged(); - } else { - queueInfoBuilder_.addMessage(index, value); - } - return this; - } - public Builder addQueueInfo( - com.alibaba.rocketmq.common.protocol.MQProtos.QueueInfo.Builder builderForValue) { - if (queueInfoBuilder_ == null) { - ensureQueueInfoIsMutable(); - queueInfo_.add(builderForValue.build()); - onChanged(); - } else { - queueInfoBuilder_.addMessage(builderForValue.build()); - } - return this; - } - public Builder addQueueInfo( - int index, com.alibaba.rocketmq.common.protocol.MQProtos.QueueInfo.Builder builderForValue) { - if (queueInfoBuilder_ == null) { - ensureQueueInfoIsMutable(); - queueInfo_.add(index, builderForValue.build()); - onChanged(); - } else { - queueInfoBuilder_.addMessage(index, builderForValue.build()); - } - return this; - } - public Builder addAllQueueInfo( - java.lang.Iterable values) { - if (queueInfoBuilder_ == null) { - ensureQueueInfoIsMutable(); - super.addAll(values, queueInfo_); - onChanged(); - } else { - queueInfoBuilder_.addAllMessages(values); - } - return this; - } - public Builder clearQueueInfo() { - if (queueInfoBuilder_ == null) { - queueInfo_ = java.util.Collections.emptyList(); - bitField0_ = (bitField0_ & ~0x00000002); - onChanged(); - } else { - queueInfoBuilder_.clear(); - } - return this; - } - public Builder removeQueueInfo(int index) { - if (queueInfoBuilder_ == null) { - ensureQueueInfoIsMutable(); - queueInfo_.remove(index); - onChanged(); - } else { - queueInfoBuilder_.remove(index); - } - return this; - } - public com.alibaba.rocketmq.common.protocol.MQProtos.QueueInfo.Builder getQueueInfoBuilder( - int index) { - return getQueueInfoFieldBuilder().getBuilder(index); - } - public com.alibaba.rocketmq.common.protocol.MQProtos.QueueInfoOrBuilder getQueueInfoOrBuilder( - int index) { - if (queueInfoBuilder_ == null) { - return queueInfo_.get(index); } else { - return queueInfoBuilder_.getMessageOrBuilder(index); - } - } - public java.util.List - getQueueInfoOrBuilderList() { - if (queueInfoBuilder_ != null) { - return queueInfoBuilder_.getMessageOrBuilderList(); - } else { - return java.util.Collections.unmodifiableList(queueInfo_); - } - } - public com.alibaba.rocketmq.common.protocol.MQProtos.QueueInfo.Builder addQueueInfoBuilder() { - return getQueueInfoFieldBuilder().addBuilder( - com.alibaba.rocketmq.common.protocol.MQProtos.QueueInfo.getDefaultInstance()); - } - public com.alibaba.rocketmq.common.protocol.MQProtos.QueueInfo.Builder addQueueInfoBuilder( - int index) { - return getQueueInfoFieldBuilder().addBuilder( - index, com.alibaba.rocketmq.common.protocol.MQProtos.QueueInfo.getDefaultInstance()); - } - public java.util.List - getQueueInfoBuilderList() { - return getQueueInfoFieldBuilder().getBuilderList(); - } - private com.google.protobuf.RepeatedFieldBuilder< - com.alibaba.rocketmq.common.protocol.MQProtos.QueueInfo, com.alibaba.rocketmq.common.protocol.MQProtos.QueueInfo.Builder, com.alibaba.rocketmq.common.protocol.MQProtos.QueueInfoOrBuilder> - getQueueInfoFieldBuilder() { - if (queueInfoBuilder_ == null) { - queueInfoBuilder_ = new com.google.protobuf.RepeatedFieldBuilder< - com.alibaba.rocketmq.common.protocol.MQProtos.QueueInfo, com.alibaba.rocketmq.common.protocol.MQProtos.QueueInfo.Builder, com.alibaba.rocketmq.common.protocol.MQProtos.QueueInfoOrBuilder>( - queueInfo_, - ((bitField0_ & 0x00000002) == 0x00000002), - getParentForChildren(), - isClean()); - queueInfo_ = null; - } - return queueInfoBuilder_; - } - - // @@protoc_insertion_point(builder_scope:rocketmq.TopicQueuePair) - } - - static { - defaultInstance = new TopicQueuePair(true); - defaultInstance.initFields(); - } - - // @@protoc_insertion_point(class_scope:rocketmq.TopicQueuePair) - } - - public interface BrokerDataPairOrBuilder - extends com.google.protobuf.MessageOrBuilder { - - // required string brokerName = 1; - boolean hasBrokerName(); - String getBrokerName(); - - // required .rocketmq.BrokerInfo brokerInfo = 2; - boolean hasBrokerInfo(); - com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo getBrokerInfo(); - com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfoOrBuilder getBrokerInfoOrBuilder(); - } - public static final class BrokerDataPair extends - com.google.protobuf.GeneratedMessage - implements BrokerDataPairOrBuilder { - // Use BrokerDataPair.newBuilder() to construct. - private BrokerDataPair(Builder builder) { - super(builder); - } - private BrokerDataPair(boolean noInit) {} - - private static final BrokerDataPair defaultInstance; - public static BrokerDataPair getDefaultInstance() { - return defaultInstance; - } - - public BrokerDataPair getDefaultInstanceForType() { - return defaultInstance; - } - - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return com.alibaba.rocketmq.common.protocol.MQProtos.internal_static_rocketmq_BrokerDataPair_descriptor; - } - - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return com.alibaba.rocketmq.common.protocol.MQProtos.internal_static_rocketmq_BrokerDataPair_fieldAccessorTable; - } - - private int bitField0_; - // required string brokerName = 1; - public static final int BROKERNAME_FIELD_NUMBER = 1; - private java.lang.Object brokerName_; - public boolean hasBrokerName() { - return ((bitField0_ & 0x00000001) == 0x00000001); - } - public String getBrokerName() { - java.lang.Object ref = brokerName_; - if (ref instanceof String) { - return (String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - String s = bs.toStringUtf8(); - if (com.google.protobuf.Internal.isValidUtf8(bs)) { - brokerName_ = s; - } - return s; - } - } - private com.google.protobuf.ByteString getBrokerNameBytes() { - java.lang.Object ref = brokerName_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8((String) ref); - brokerName_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - // required .rocketmq.BrokerInfo brokerInfo = 2; - public static final int BROKERINFO_FIELD_NUMBER = 2; - private com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo brokerInfo_; - public boolean hasBrokerInfo() { - return ((bitField0_ & 0x00000002) == 0x00000002); - } - public com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo getBrokerInfo() { - return brokerInfo_; - } - public com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfoOrBuilder getBrokerInfoOrBuilder() { - return brokerInfo_; - } - - private void initFields() { - brokerName_ = ""; - brokerInfo_ = com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo.getDefaultInstance(); - } - private byte memoizedIsInitialized = -1; - public final boolean isInitialized() { - byte isInitialized = memoizedIsInitialized; - if (isInitialized != -1) return isInitialized == 1; - - if (!hasBrokerName()) { - memoizedIsInitialized = 0; - return false; - } - if (!hasBrokerInfo()) { - memoizedIsInitialized = 0; - return false; - } - if (!getBrokerInfo().isInitialized()) { - memoizedIsInitialized = 0; - return false; - } - memoizedIsInitialized = 1; - return true; - } - - public void writeTo(com.google.protobuf.CodedOutputStream output) - throws java.io.IOException { - getSerializedSize(); - if (((bitField0_ & 0x00000001) == 0x00000001)) { - output.writeBytes(1, getBrokerNameBytes()); - } - if (((bitField0_ & 0x00000002) == 0x00000002)) { - output.writeMessage(2, brokerInfo_); - } - getUnknownFields().writeTo(output); - } - - private int memoizedSerializedSize = -1; - public int getSerializedSize() { - int size = memoizedSerializedSize; - if (size != -1) return size; - - size = 0; - if (((bitField0_ & 0x00000001) == 0x00000001)) { - size += com.google.protobuf.CodedOutputStream - .computeBytesSize(1, getBrokerNameBytes()); - } - if (((bitField0_ & 0x00000002) == 0x00000002)) { - size += com.google.protobuf.CodedOutputStream - .computeMessageSize(2, brokerInfo_); - } - size += getUnknownFields().getSerializedSize(); - memoizedSerializedSize = size; - return size; - } - - private static final long serialVersionUID = 0L; - @java.lang.Override - protected java.lang.Object writeReplace() - throws java.io.ObjectStreamException { - return super.writeReplace(); - } - - public static com.alibaba.rocketmq.common.protocol.MQProtos.BrokerDataPair parseFrom( - com.google.protobuf.ByteString data) - throws com.google.protobuf.InvalidProtocolBufferException { - return newBuilder().mergeFrom(data).buildParsed(); - } - public static com.alibaba.rocketmq.common.protocol.MQProtos.BrokerDataPair parseFrom( - com.google.protobuf.ByteString data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return newBuilder().mergeFrom(data, extensionRegistry) - .buildParsed(); - } - public static com.alibaba.rocketmq.common.protocol.MQProtos.BrokerDataPair parseFrom(byte[] data) - throws com.google.protobuf.InvalidProtocolBufferException { - return newBuilder().mergeFrom(data).buildParsed(); - } - public static com.alibaba.rocketmq.common.protocol.MQProtos.BrokerDataPair parseFrom( - byte[] data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return newBuilder().mergeFrom(data, extensionRegistry) - .buildParsed(); - } - public static com.alibaba.rocketmq.common.protocol.MQProtos.BrokerDataPair parseFrom(java.io.InputStream input) - throws java.io.IOException { - return newBuilder().mergeFrom(input).buildParsed(); - } - public static com.alibaba.rocketmq.common.protocol.MQProtos.BrokerDataPair parseFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return newBuilder().mergeFrom(input, extensionRegistry) - .buildParsed(); - } - public static com.alibaba.rocketmq.common.protocol.MQProtos.BrokerDataPair parseDelimitedFrom(java.io.InputStream input) - throws java.io.IOException { - Builder builder = newBuilder(); - if (builder.mergeDelimitedFrom(input)) { - return builder.buildParsed(); - } else { - return null; - } - } - public static com.alibaba.rocketmq.common.protocol.MQProtos.BrokerDataPair parseDelimitedFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - Builder builder = newBuilder(); - if (builder.mergeDelimitedFrom(input, extensionRegistry)) { - return builder.buildParsed(); - } else { - return null; - } - } - public static com.alibaba.rocketmq.common.protocol.MQProtos.BrokerDataPair parseFrom( - com.google.protobuf.CodedInputStream input) - throws java.io.IOException { - return newBuilder().mergeFrom(input).buildParsed(); - } - public static com.alibaba.rocketmq.common.protocol.MQProtos.BrokerDataPair parseFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return newBuilder().mergeFrom(input, extensionRegistry) - .buildParsed(); - } - - public static Builder newBuilder() { return Builder.create(); } - public Builder newBuilderForType() { return newBuilder(); } - public static Builder newBuilder(com.alibaba.rocketmq.common.protocol.MQProtos.BrokerDataPair prototype) { - return newBuilder().mergeFrom(prototype); - } - public Builder toBuilder() { return newBuilder(this); } - - @java.lang.Override - protected Builder newBuilderForType( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - Builder builder = new Builder(parent); - return builder; - } - public static final class Builder extends - com.google.protobuf.GeneratedMessage.Builder - implements com.alibaba.rocketmq.common.protocol.MQProtos.BrokerDataPairOrBuilder { - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return com.alibaba.rocketmq.common.protocol.MQProtos.internal_static_rocketmq_BrokerDataPair_descriptor; - } - - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return com.alibaba.rocketmq.common.protocol.MQProtos.internal_static_rocketmq_BrokerDataPair_fieldAccessorTable; - } - - // Construct using com.alibaba.rocketmq.common.protocol.MQProtos.BrokerDataPair.newBuilder() - private Builder() { - maybeForceBuilderInitialization(); - } - - private Builder(BuilderParent parent) { - super(parent); - maybeForceBuilderInitialization(); - } - private void maybeForceBuilderInitialization() { - if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) { - getBrokerInfoFieldBuilder(); - } - } - private static Builder create() { - return new Builder(); - } - - public Builder clear() { - super.clear(); - brokerName_ = ""; - bitField0_ = (bitField0_ & ~0x00000001); - if (brokerInfoBuilder_ == null) { - brokerInfo_ = com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo.getDefaultInstance(); - } else { - brokerInfoBuilder_.clear(); - } - bitField0_ = (bitField0_ & ~0x00000002); - return this; - } - - public Builder clone() { - return create().mergeFrom(buildPartial()); - } - - public com.google.protobuf.Descriptors.Descriptor - getDescriptorForType() { - return com.alibaba.rocketmq.common.protocol.MQProtos.BrokerDataPair.getDescriptor(); - } - - public com.alibaba.rocketmq.common.protocol.MQProtos.BrokerDataPair getDefaultInstanceForType() { - return com.alibaba.rocketmq.common.protocol.MQProtos.BrokerDataPair.getDefaultInstance(); - } - - public com.alibaba.rocketmq.common.protocol.MQProtos.BrokerDataPair build() { - com.alibaba.rocketmq.common.protocol.MQProtos.BrokerDataPair result = buildPartial(); - if (!result.isInitialized()) { - throw newUninitializedMessageException(result); - } - return result; - } - - private com.alibaba.rocketmq.common.protocol.MQProtos.BrokerDataPair buildParsed() - throws com.google.protobuf.InvalidProtocolBufferException { - com.alibaba.rocketmq.common.protocol.MQProtos.BrokerDataPair result = buildPartial(); - if (!result.isInitialized()) { - throw newUninitializedMessageException( - result).asInvalidProtocolBufferException(); - } - return result; - } - - public com.alibaba.rocketmq.common.protocol.MQProtos.BrokerDataPair buildPartial() { - com.alibaba.rocketmq.common.protocol.MQProtos.BrokerDataPair result = new com.alibaba.rocketmq.common.protocol.MQProtos.BrokerDataPair(this); - int from_bitField0_ = bitField0_; - int to_bitField0_ = 0; - if (((from_bitField0_ & 0x00000001) == 0x00000001)) { - to_bitField0_ |= 0x00000001; - } - result.brokerName_ = brokerName_; - if (((from_bitField0_ & 0x00000002) == 0x00000002)) { - to_bitField0_ |= 0x00000002; - } - if (brokerInfoBuilder_ == null) { - result.brokerInfo_ = brokerInfo_; - } else { - result.brokerInfo_ = brokerInfoBuilder_.build(); - } - result.bitField0_ = to_bitField0_; - onBuilt(); - return result; - } - - public Builder mergeFrom(com.google.protobuf.Message other) { - if (other instanceof com.alibaba.rocketmq.common.protocol.MQProtos.BrokerDataPair) { - return mergeFrom((com.alibaba.rocketmq.common.protocol.MQProtos.BrokerDataPair)other); - } else { - super.mergeFrom(other); - return this; - } - } - - public Builder mergeFrom(com.alibaba.rocketmq.common.protocol.MQProtos.BrokerDataPair other) { - if (other == com.alibaba.rocketmq.common.protocol.MQProtos.BrokerDataPair.getDefaultInstance()) return this; - if (other.hasBrokerName()) { - setBrokerName(other.getBrokerName()); - } - if (other.hasBrokerInfo()) { - mergeBrokerInfo(other.getBrokerInfo()); - } - this.mergeUnknownFields(other.getUnknownFields()); - return this; - } - - public final boolean isInitialized() { - if (!hasBrokerName()) { - - return false; - } - if (!hasBrokerInfo()) { - - return false; - } - if (!getBrokerInfo().isInitialized()) { - - return false; + + public enum MQRequestCode { + // Broker 发送消息 + SEND_MESSAGE(0, 10), + // Broker 订阅消息 + PULL_MESSAGE(1, 11), + // Broker 查询消息 + QUERY_MESSAGE(2, 12), + // Broker 查询Broker Offset + QUERY_BROKER_OFFSET(3, 13), + // Broker 查询Consumer Offset + QUERY_CONSUMER_OFFSET(4, 14), + // Broker 更新Consumer Offset + UPDATE_CONSUMER_OFFSET(5, 15), + // Broker 更新或者增加一个Topic + UPDATE_AND_CREATE_TOPIC(6, 17), + // Broker 获取所有Topic的配置(Slave和Namesrv都会向Master请求此配置) + GET_ALL_TOPIC_CONFIG(8, 21), + // Broker 获取所有Topic配置(Slave和Namesrv都会向Master请求此配置) + GET_TOPIC_CONFIG_LIST(9, 22), + // Broker 获取所有Topic名称列表 + GET_TOPIC_NAME_LIST(10, 23), + // Broker 更新Broker上的配置 + UPDATE_BROKER_CONFIG(12, 25), + // Broker 获取Broker上的配置 + GET_BROKER_CONFIG(13, 26), + // Broker 触发Broker删除文件 + TRIGGER_DELETE_FILES(14, 27), + // Broker 获取Broker运行时信息 + GET_BROKER_RUNTIME_INFO(15, 28), + // Broker 根据时间查询队列的Offset + SEARCH_OFFSET_BY_TIMESTAMP(16, 29), + // Broker 查询队列最大Offset + GET_MAX_OFFSET(17, 30), + // Broker 查询队列最小Offset + GET_MIN_OFFSET(18, 31), + // Broker 查询队列最早消息对应时间 + GET_EARLIEST_MSG_STORETIME(19, 32), + // Broker 根据消息ID来查询消息 + VIEW_MESSAGE_BY_ID(20, 33), + // Broker Client向Client发送心跳,并注册自身 + HEART_BEAT(21, 34), + // Broker Client注销 + UNREGISTER_CLIENT(22, 35), + // Broker Consumer将处理不了的消息发回服务器 + CONSUMER_SEND_MSG_BACK(23, 36), + // Broker Commit或者Rollback事务 + END_TRANSACTION(24, 37), + // Broker 获取ConsumerId列表通过GroupName + GET_CONSUMER_LIST_BY_GROUP(25, 38), + // Broker 主动向Producer回查事务状态 + CHECK_TRANSACTION_STATE(26, 39), + // Broker Broker通知Consumer列表变化 + NOTIFY_CONSUMER_IDS_CHANGED(27, 40), + // Broker Consumer向Master锁定队列 + LOCK_BATCH_MQ(28, 41), + // Broker Consumer向Master解锁队列 + UNLOCK_BATCH_MQ(29, 42), + // Broker 获取所有Consumer Offset + GET_ALL_CONSUMER_OFFSET(30, 43), + // Broker 获取所有定时进度 + GET_ALL_DELAY_OFFSET(32, 45), + // Namesrv 向Namesrv追加KV配置 + PUT_KV_CONFIG(33, 100), + // Namesrv 从Namesrv获取KV配置 + GET_KV_CONFIG(34, 101), + // Namesrv 从Namesrv获取KV配置 + DELETE_KV_CONFIG(35, 102), + // Namesrv 注册一个Broker,数据都是持久化的,如果存在则覆盖配置 + REGISTER_BROKER(36, 103), + // Namesrv 卸载一个Broker,数据都是持久化的 + UNREGISTER_BROKER(37, 104), + // Namesrv 根据Topic获取Broker Name、队列数(包含读队列与写队列) + GET_ROUTEINTO_BY_TOPIC(38, 105), + // Namesrv 获取注册到Name Server的所有Broker集群信息 + GET_BROKER_CLUSTER_INFO(39, 106), + + // Broker 更新或者增加一个订阅组 + UPDATE_AND_CREATE_SUBSCRIPTIONGROUP(40, 200), + GET_ALL_SUBSCRIPTIONGROUP_CONFIG(41, 201), + + // 统计信息 + GET_TOPIC_STATS_INFO(42, 202), + + // 获取Consumer连接列表,附带订阅关系 + GET_CONSUMER_CONNECTION_LIST(43, 203), + // 获取Producer连接列表 + GET_PRODUCER_CONNECTION_LIST(44, 204), + + // 清除Name Server中某个Broker的写权限 + WIPE_WRITE_PERM_OF_BROKER(45, 205), + + // 从Name Server获取完整Topic列表 + GET_ALL_TOPIC_LIST_FROM_NAMESERVER(46, 206), + // 从Broker删除订阅组 + DELETE_SUBSCRIPTIONGROUP(47, 207), + // 从Broker获取消费状态(进度) + GET_CONSUME_STATS(48, 208), + // Suspend Consumer消费过程 + SUSPEND_CONSUMER(49, 209), + // Resume Consumer消费过程 + RESUME_CONSUMER(50, 210), + // 重置Consumer Offset + RESET_CONSUMER_OFFSET_IN_CONSUMER(51, 211), + // 重置Consumer Offset + RESET_CONSUMER_OFFSET_IN_BROKER(52, 212), + // 调整Consumer线程池数量 + ADJUST_CONSUMER_THREAD_POOL(53, 213), + // 查询消息被哪些消费组消费 + WHO_CONSUME_THE_MESSAGE(54, 214), + // 从Broker删除Topic配置 + DELETE_TOPIC_IN_BROKER(55, 215), + // 从Namesrv删除Topic配置 + DELETE_TOPIC_IN_NAMESRV(56, 216), + // Namesrv 通过 project 获取所有的 server ip 信息 + GET_KV_CONFIG_BY_VALUE(57, 217), + // 删除指定 project group 下的所有 server ip 信息 + DELETE_KV_CONFIG_BY_VALUE(58, 218), + // 通过NameSpace获取所有的KV List + GET_KVLIST_BY_NAMESPACE(59, 219), + // offset 重置 + RESET_CONSUMER_CLIENT_OFFSET(60, 220), + // 客户端订阅消息 + GET_CONSUMER_STATUS_FROM_CLIENT(61, 221), + // 通知 broker 调用 offset 重置处理 + INVOKE_BROKER_TO_RESET_OFFSET(62, 222), + // 通知 broker 调用客户端订阅消息处理 + INVOKE_BROKER_TO_GET_CONSUMER_STATUS(63, 223); + + // Broker 发送消息 + public static final int SEND_MESSAGE_VALUE = 10; + // Broker 订阅消息 + public static final int PULL_MESSAGE_VALUE = 11; + // Broker 查询消息 + public static final int QUERY_MESSAGE_VALUE = 12; + // Broker 查询Broker Offset + public static final int QUERY_BROKER_OFFSET_VALUE = 13; + // Broker 查询Consumer Offset + public static final int QUERY_CONSUMER_OFFSET_VALUE = 14; + // Broker 更新Consumer Offset + public static final int UPDATE_CONSUMER_OFFSET_VALUE = 15; + // Broker 更新或者增加一个Topic + public static final int UPDATE_AND_CREATE_TOPIC_VALUE = 17; + // Broker 获取所有Topic的配置(Slave和Namesrv都会向Master请求此配置) + public static final int GET_ALL_TOPIC_CONFIG_VALUE = 21; + // Broker 获取所有Topic配置(Slave和Namesrv都会向Master请求此配置) + public static final int GET_TOPIC_CONFIG_LIST_VALUE = 22; + // Broker 获取所有Topic名称列表 + public static final int GET_TOPIC_NAME_LIST_VALUE = 23; + // Broker 更新Broker上的配置 + public static final int UPDATE_BROKER_CONFIG_VALUE = 25; + // Broker 获取Broker上的配置 + public static final int GET_BROKER_CONFIG_VALUE = 26; + // Broker 触发Broker删除文件 + public static final int TRIGGER_DELETE_FILES_VALUE = 27; + // Broker 获取Broker运行时信息 + public static final int GET_BROKER_RUNTIME_INFO_VALUE = 28; + // Broker 根据时间查询队列的Offset + public static final int SEARCH_OFFSET_BY_TIMESTAMP_VALUE = 29; + // Broker 查询队列最大Offset + public static final int GET_MAX_OFFSET_VALUE = 30; + // Broker 查询队列最小Offset + public static final int GET_MIN_OFFSET_VALUE = 31; + // Broker 查询队列最早消息对应时间 + public static final int GET_EARLIEST_MSG_STORETIME_VALUE = 32; + // Broker 根据消息ID来查询消息 + public static final int VIEW_MESSAGE_BY_ID_VALUE = 33; + // Broker Client向Client发送心跳,并注册自身 + public static final int HEART_BEAT_VALUE = 34; + // Broker Client注销 + public static final int UNREGISTER_CLIENT_VALUE = 35; + // Broker Consumer将处理不了的消息发回服务器 + public static final int CONSUMER_SEND_MSG_BACK_VALUE = 36; + // Broker Commit或者Rollback事务 + public static final int END_TRANSACTION_VALUE = 37; + // Broker 获取ConsumerId列表通过GroupName + public static final int GET_CONSUMER_LIST_BY_GROUP_VALUE = 38; + // Broker 主动向Producer回查事务状态 + public static final int CHECK_TRANSACTION_STATE_VALUE = 39; + // Broker Broker通知Consumer列表变化 + public static final int NOTIFY_CONSUMER_IDS_CHANGED_VALUE = 40; + // Broker Consumer向Master锁定队列 + public static final int LOCK_BATCH_MQ_VALUE = 41; + // Broker Consumer向Master解锁队列 + public static final int UNLOCK_BATCH_MQ_VALUE = 42; + // Broker 获取所有Consumer Offset + public static final int GET_ALL_CONSUMER_OFFSET_VALUE = 43; + // Broker 获取所有定时进度 + public static final int GET_ALL_DELAY_OFFSET_VALUE = 45; + // Namesrv 向Namesrv追加KV配置 + public static final int PUT_KV_CONFIG_VALUE = 100; + // Namesrv 从Namesrv获取KV配置 + public static final int GET_KV_CONFIG_VALUE = 101; + // Namesrv 从Namesrv获取KV配置 + public static final int DELETE_KV_CONFIG_VALUE = 102; + // Namesrv 注册一个Broker,数据都是持久化的,如果存在则覆盖配置 + public static final int REGISTER_BROKER_VALUE = 103; + // Namesrv 卸载一个Broker,数据都是持久化的 + public static final int UNREGISTER_BROKER_VALUE = 104; + // Namesrv 根据Topic获取Broker Name、队列数(包含读队列与写队列) + public static final int GET_ROUTEINTO_BY_TOPIC_VALUE = 105; + // Namesrv 获取注册到Name Server的所有Broker集群信息 + public static final int GET_BROKER_CLUSTER_INFO_VALUE = 106; + public static final int UPDATE_AND_CREATE_SUBSCRIPTIONGROUP_VALUE = 200; + public static final int GET_ALL_SUBSCRIPTIONGROUP_CONFIG_VALUE = 201; + public static final int GET_TOPIC_STATS_INFO_VALUE = 202; + public static final int GET_CONSUMER_CONNECTION_LIST_VALUE = 203; + public static final int GET_PRODUCER_CONNECTION_LIST_VALUE = 204; + public static final int WIPE_WRITE_PERM_OF_BROKER_VALUE = 205; + + // 从Name Server获取完整Topic列表 + public static final int GET_ALL_TOPIC_LIST_FROM_NAMESERVER_VALUE = 206; + // 从Broker删除订阅组 + public static final int DELETE_SUBSCRIPTIONGROUP_VALUE = 207; + // 从Broker获取消费状态(进度) + public static final int GET_CONSUME_STATS_VALUE = 208; + // Suspend Consumer消费过程 + public static final int SUSPEND_CONSUMER_VALUE = 209; + // Resume Consumer消费过程 + public static final int RESUME_CONSUMER_VALUE = 210; + // 重置Consumer Offset + public static final int RESET_CONSUMER_OFFSET_IN_CONSUMER_VALUE = 211; + // 重置Consumer Offset + public static final int RESET_CONSUMER_OFFSET_IN_BROKER_VALUE = 212; + // 调整Consumer线程池数量 + public static final int ADJUST_CONSUMER_THREAD_POOL_VALUE = 213; + // 查询消息被哪些消费组消费 + public static final int WHO_CONSUME_THE_MESSAGE_VALUE = 214; + + // 从Broker删除Topic配置 + public static final int DELETE_TOPIC_IN_BROKER_VALUE = 215; + // 从Namesrv删除Topic配置 + public static final int DELETE_TOPIC_IN_NAMESRV_VALUE = 216; + // Namesrv 通过 project 获取所有的 server ip 信息 + public static final int GET_KV_CONFIG_BY_VALUE_VALUE = 217; + // Namesrv 删除指定 project group 下的所有 server ip 信息 + public static final int DELETE_KV_CONFIG_BY_VALUE_VALUE = 218; + // 通过NameSpace获取所有的KV List + public static final int GET_KVLIST_BY_NAMESPACE_VALUE = 219; + + // offset 重置 + public static final int RESET_CONSUMER_CLIENT_OFFSET_VALUE = 220; + // 客户端订阅消息 + public static final int GET_CONSUMER_STATUS_FROM_CLIENT_VALUE = 221; + // 通知 broker 调用 offset 重置处理 + public static final int INVOKE_BROKER_TO_RESET_OFFSET_VALUE = 222; + // 通知 broker 调用客户端订阅消息处理 + public static final int INVOKE_BROKER_TO_GET_CONSUMER_STATUS_VALUE = 223; + + private final int index; + private final int value; + + + private MQRequestCode(int index, int value) { + this.index = index; + this.value = value; } - return true; - } - - public Builder mergeFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - com.google.protobuf.UnknownFieldSet.Builder unknownFields = - com.google.protobuf.UnknownFieldSet.newBuilder( - this.getUnknownFields()); - while (true) { - int tag = input.readTag(); - switch (tag) { - case 0: - this.setUnknownFields(unknownFields.build()); - onChanged(); - return this; - default: { - if (!parseUnknownField(input, unknownFields, - extensionRegistry, tag)) { - this.setUnknownFields(unknownFields.build()); - onChanged(); - return this; - } - break; - } - case 10: { - bitField0_ |= 0x00000001; - brokerName_ = input.readBytes(); - break; - } - case 18: { - com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo.Builder subBuilder = com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo.newBuilder(); - if (hasBrokerInfo()) { - subBuilder.mergeFrom(getBrokerInfo()); - } - input.readMessage(subBuilder, extensionRegistry); - setBrokerInfo(subBuilder.buildPartial()); - break; + + + public static MQRequestCode valueOf(int value) { + switch (value) { + case 10: + return SEND_MESSAGE; + case 11: + return PULL_MESSAGE; + case 12: + return QUERY_MESSAGE; + case 13: + return QUERY_BROKER_OFFSET; + case 14: + return QUERY_CONSUMER_OFFSET; + case 15: + return UPDATE_CONSUMER_OFFSET; + case 17: + return UPDATE_AND_CREATE_TOPIC; + case 21: + return GET_ALL_TOPIC_CONFIG; + case 22: + return GET_TOPIC_CONFIG_LIST; + case 23: + return GET_TOPIC_NAME_LIST; + case 25: + return UPDATE_BROKER_CONFIG; + case 26: + return GET_BROKER_CONFIG; + case 27: + return TRIGGER_DELETE_FILES; + case 28: + return GET_BROKER_RUNTIME_INFO; + case 29: + return SEARCH_OFFSET_BY_TIMESTAMP; + case 30: + return GET_MAX_OFFSET; + case 31: + return GET_MIN_OFFSET; + case 32: + return GET_EARLIEST_MSG_STORETIME; + case 33: + return VIEW_MESSAGE_BY_ID; + case 34: + return HEART_BEAT; + case 35: + return UNREGISTER_CLIENT; + case 36: + return CONSUMER_SEND_MSG_BACK; + case 37: + return END_TRANSACTION; + case 38: + return GET_CONSUMER_LIST_BY_GROUP; + case 39: + return CHECK_TRANSACTION_STATE; + case 40: + return NOTIFY_CONSUMER_IDS_CHANGED; + case 41: + return LOCK_BATCH_MQ; + case 42: + return UNLOCK_BATCH_MQ; + case 43: + return GET_ALL_CONSUMER_OFFSET; + case 45: + return GET_ALL_DELAY_OFFSET; + case 100: + return PUT_KV_CONFIG; + case 101: + return GET_KV_CONFIG; + case 102: + return DELETE_KV_CONFIG; + case 103: + return REGISTER_BROKER; + case 104: + return UNREGISTER_BROKER; + case 105: + return GET_ROUTEINTO_BY_TOPIC; + case 106: + return GET_BROKER_CLUSTER_INFO; + + case 200: + return UPDATE_AND_CREATE_SUBSCRIPTIONGROUP; + case 201: + return GET_ALL_SUBSCRIPTIONGROUP_CONFIG; + case 202: + return GET_TOPIC_STATS_INFO; + + case 203: + return GET_CONSUMER_CONNECTION_LIST; + case 204: + return GET_PRODUCER_CONNECTION_LIST; + case 205: + return WIPE_WRITE_PERM_OF_BROKER; + + case 206: + return GET_ALL_TOPIC_LIST_FROM_NAMESERVER; + case 207: + return DELETE_SUBSCRIPTIONGROUP; + case 208: + return GET_CONSUME_STATS; + case 209: + return SUSPEND_CONSUMER; + case 210: + return RESUME_CONSUMER; + case 211: + return RESET_CONSUMER_OFFSET_IN_CONSUMER; + case 212: + return RESET_CONSUMER_OFFSET_IN_BROKER; + case 213: + return ADJUST_CONSUMER_THREAD_POOL; + case 214: + return WHO_CONSUME_THE_MESSAGE; + case 215: + return DELETE_TOPIC_IN_BROKER; + case 216: + return DELETE_TOPIC_IN_NAMESRV; + case 217: + return GET_KV_CONFIG_BY_VALUE; + case 218: + return DELETE_KV_CONFIG_BY_VALUE; + case GET_KVLIST_BY_NAMESPACE_VALUE: + return GET_KVLIST_BY_NAMESPACE; + case RESET_CONSUMER_CLIENT_OFFSET_VALUE: + return RESET_CONSUMER_CLIENT_OFFSET; + case GET_CONSUMER_STATUS_FROM_CLIENT_VALUE: + return GET_CONSUMER_STATUS_FROM_CLIENT; + case INVOKE_BROKER_TO_RESET_OFFSET_VALUE: + return INVOKE_BROKER_TO_RESET_OFFSET; + case INVOKE_BROKER_TO_GET_CONSUMER_STATUS_VALUE: + return INVOKE_BROKER_TO_GET_CONSUMER_STATUS; + default: + return null; } - } - } - } - - private int bitField0_; - - // required string brokerName = 1; - private java.lang.Object brokerName_ = ""; - public boolean hasBrokerName() { - return ((bitField0_ & 0x00000001) == 0x00000001); - } - public String getBrokerName() { - java.lang.Object ref = brokerName_; - if (!(ref instanceof String)) { - String s = ((com.google.protobuf.ByteString) ref).toStringUtf8(); - brokerName_ = s; - return s; - } else { - return (String) ref; - } - } - public Builder setBrokerName(String value) { - if (value == null) { - throw new NullPointerException(); - } - bitField0_ |= 0x00000001; - brokerName_ = value; - onChanged(); - return this; - } - public Builder clearBrokerName() { - bitField0_ = (bitField0_ & ~0x00000001); - brokerName_ = getDefaultInstance().getBrokerName(); - onChanged(); - return this; - } - void setBrokerName(com.google.protobuf.ByteString value) { - bitField0_ |= 0x00000001; - brokerName_ = value; - onChanged(); - } - - // required .rocketmq.BrokerInfo brokerInfo = 2; - private com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo brokerInfo_ = com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo.getDefaultInstance(); - private com.google.protobuf.SingleFieldBuilder< - com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo, com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo.Builder, com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfoOrBuilder> brokerInfoBuilder_; - public boolean hasBrokerInfo() { - return ((bitField0_ & 0x00000002) == 0x00000002); - } - public com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo getBrokerInfo() { - if (brokerInfoBuilder_ == null) { - return brokerInfo_; - } else { - return brokerInfoBuilder_.getMessage(); - } - } - public Builder setBrokerInfo(com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo value) { - if (brokerInfoBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - brokerInfo_ = value; - onChanged(); - } else { - brokerInfoBuilder_.setMessage(value); - } - bitField0_ |= 0x00000002; - return this; - } - public Builder setBrokerInfo( - com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo.Builder builderForValue) { - if (brokerInfoBuilder_ == null) { - brokerInfo_ = builderForValue.build(); - onChanged(); - } else { - brokerInfoBuilder_.setMessage(builderForValue.build()); - } - bitField0_ |= 0x00000002; - return this; - } - public Builder mergeBrokerInfo(com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo value) { - if (brokerInfoBuilder_ == null) { - if (((bitField0_ & 0x00000002) == 0x00000002) && - brokerInfo_ != com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo.getDefaultInstance()) { - brokerInfo_ = - com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo.newBuilder(brokerInfo_).mergeFrom(value).buildPartial(); - } else { - brokerInfo_ = value; - } - onChanged(); - } else { - brokerInfoBuilder_.mergeFrom(value); - } - bitField0_ |= 0x00000002; - return this; - } - public Builder clearBrokerInfo() { - if (brokerInfoBuilder_ == null) { - brokerInfo_ = com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo.getDefaultInstance(); - onChanged(); - } else { - brokerInfoBuilder_.clear(); } - bitField0_ = (bitField0_ & ~0x00000002); - return this; - } - public com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo.Builder getBrokerInfoBuilder() { - bitField0_ |= 0x00000002; - onChanged(); - return getBrokerInfoFieldBuilder().getBuilder(); - } - public com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfoOrBuilder getBrokerInfoOrBuilder() { - if (brokerInfoBuilder_ != null) { - return brokerInfoBuilder_.getMessageOrBuilder(); - } else { - return brokerInfo_; - } - } - private com.google.protobuf.SingleFieldBuilder< - com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo, com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo.Builder, com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfoOrBuilder> - getBrokerInfoFieldBuilder() { - if (brokerInfoBuilder_ == null) { - brokerInfoBuilder_ = new com.google.protobuf.SingleFieldBuilder< - com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo, com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo.Builder, com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfoOrBuilder>( - brokerInfo_, - getParentForChildren(), - isClean()); - brokerInfo_ = null; - } - return brokerInfoBuilder_; - } - - // @@protoc_insertion_point(builder_scope:rocketmq.BrokerDataPair) - } - - static { - defaultInstance = new BrokerDataPair(true); - defaultInstance.initFields(); - } - - // @@protoc_insertion_point(class_scope:rocketmq.BrokerDataPair) - } - - public interface TopicRuntimeInfoOrBuilder - extends com.google.protobuf.MessageOrBuilder { - - // repeated .rocketmq.TopicQueuePair topicBrokers = 1; - java.util.List - getTopicBrokersList(); - com.alibaba.rocketmq.common.protocol.MQProtos.TopicQueuePair getTopicBrokers(int index); - int getTopicBrokersCount(); - java.util.List - getTopicBrokersOrBuilderList(); - com.alibaba.rocketmq.common.protocol.MQProtos.TopicQueuePairOrBuilder getTopicBrokersOrBuilder( - int index); - - // required .remoting.NVPairList topicOrderConfs = 2; - boolean hasTopicOrderConfs(); - com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPairList getTopicOrderConfs(); - com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPairListOrBuilder getTopicOrderConfsOrBuilder(); - - // repeated .rocketmq.BrokerDataPair brokers = 3; - java.util.List - getBrokersList(); - com.alibaba.rocketmq.common.protocol.MQProtos.BrokerDataPair getBrokers(int index); - int getBrokersCount(); - java.util.List - getBrokersOrBuilderList(); - com.alibaba.rocketmq.common.protocol.MQProtos.BrokerDataPairOrBuilder getBrokersOrBuilder( - int index); - - // required .remoting.StringList brokerList = 4; - boolean hasBrokerList(); - com.alibaba.rocketmq.remoting.protocol.RemotingProtos.StringList getBrokerList(); - com.alibaba.rocketmq.remoting.protocol.RemotingProtos.StringListOrBuilder getBrokerListOrBuilder(); - } - public static final class TopicRuntimeInfo extends - com.google.protobuf.GeneratedMessage - implements TopicRuntimeInfoOrBuilder { - // Use TopicRuntimeInfo.newBuilder() to construct. - private TopicRuntimeInfo(Builder builder) { - super(builder); - } - private TopicRuntimeInfo(boolean noInit) {} - - private static final TopicRuntimeInfo defaultInstance; - public static TopicRuntimeInfo getDefaultInstance() { - return defaultInstance; - } - - public TopicRuntimeInfo getDefaultInstanceForType() { - return defaultInstance; - } - - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return com.alibaba.rocketmq.common.protocol.MQProtos.internal_static_rocketmq_TopicRuntimeInfo_descriptor; - } - - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return com.alibaba.rocketmq.common.protocol.MQProtos.internal_static_rocketmq_TopicRuntimeInfo_fieldAccessorTable; - } - - private int bitField0_; - // repeated .rocketmq.TopicQueuePair topicBrokers = 1; - public static final int TOPICBROKERS_FIELD_NUMBER = 1; - private java.util.List topicBrokers_; - public java.util.List getTopicBrokersList() { - return topicBrokers_; - } - public java.util.List - getTopicBrokersOrBuilderList() { - return topicBrokers_; - } - public int getTopicBrokersCount() { - return topicBrokers_.size(); - } - public com.alibaba.rocketmq.common.protocol.MQProtos.TopicQueuePair getTopicBrokers(int index) { - return topicBrokers_.get(index); - } - public com.alibaba.rocketmq.common.protocol.MQProtos.TopicQueuePairOrBuilder getTopicBrokersOrBuilder( - int index) { - return topicBrokers_.get(index); - } - - // required .remoting.NVPairList topicOrderConfs = 2; - public static final int TOPICORDERCONFS_FIELD_NUMBER = 2; - private com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPairList topicOrderConfs_; - public boolean hasTopicOrderConfs() { - return ((bitField0_ & 0x00000001) == 0x00000001); - } - public com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPairList getTopicOrderConfs() { - return topicOrderConfs_; - } - public com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPairListOrBuilder getTopicOrderConfsOrBuilder() { - return topicOrderConfs_; - } - - // repeated .rocketmq.BrokerDataPair brokers = 3; - public static final int BROKERS_FIELD_NUMBER = 3; - private java.util.List brokers_; - public java.util.List getBrokersList() { - return brokers_; - } - public java.util.List - getBrokersOrBuilderList() { - return brokers_; - } - public int getBrokersCount() { - return brokers_.size(); - } - public com.alibaba.rocketmq.common.protocol.MQProtos.BrokerDataPair getBrokers(int index) { - return brokers_.get(index); - } - public com.alibaba.rocketmq.common.protocol.MQProtos.BrokerDataPairOrBuilder getBrokersOrBuilder( - int index) { - return brokers_.get(index); - } - - // required .remoting.StringList brokerList = 4; - public static final int BROKERLIST_FIELD_NUMBER = 4; - private com.alibaba.rocketmq.remoting.protocol.RemotingProtos.StringList brokerList_; - public boolean hasBrokerList() { - return ((bitField0_ & 0x00000002) == 0x00000002); - } - public com.alibaba.rocketmq.remoting.protocol.RemotingProtos.StringList getBrokerList() { - return brokerList_; - } - public com.alibaba.rocketmq.remoting.protocol.RemotingProtos.StringListOrBuilder getBrokerListOrBuilder() { - return brokerList_; - } - - private void initFields() { - topicBrokers_ = java.util.Collections.emptyList(); - topicOrderConfs_ = com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPairList.getDefaultInstance(); - brokers_ = java.util.Collections.emptyList(); - brokerList_ = com.alibaba.rocketmq.remoting.protocol.RemotingProtos.StringList.getDefaultInstance(); - } - private byte memoizedIsInitialized = -1; - public final boolean isInitialized() { - byte isInitialized = memoizedIsInitialized; - if (isInitialized != -1) return isInitialized == 1; - - if (!hasTopicOrderConfs()) { - memoizedIsInitialized = 0; - return false; - } - if (!hasBrokerList()) { - memoizedIsInitialized = 0; - return false; - } - for (int i = 0; i < getTopicBrokersCount(); i++) { - if (!getTopicBrokers(i).isInitialized()) { - memoizedIsInitialized = 0; - return false; + + + public int getIndex() { + return index; } - } - if (!getTopicOrderConfs().isInitialized()) { - memoizedIsInitialized = 0; - return false; - } - for (int i = 0; i < getBrokersCount(); i++) { - if (!getBrokers(i).isInitialized()) { - memoizedIsInitialized = 0; - return false; + + + public final int getNumber() { + return value; } - } - memoizedIsInitialized = 1; - return true; - } - - public void writeTo(com.google.protobuf.CodedOutputStream output) - throws java.io.IOException { - getSerializedSize(); - for (int i = 0; i < topicBrokers_.size(); i++) { - output.writeMessage(1, topicBrokers_.get(i)); - } - if (((bitField0_ & 0x00000001) == 0x00000001)) { - output.writeMessage(2, topicOrderConfs_); - } - for (int i = 0; i < brokers_.size(); i++) { - output.writeMessage(3, brokers_.get(i)); - } - if (((bitField0_ & 0x00000002) == 0x00000002)) { - output.writeMessage(4, brokerList_); - } - getUnknownFields().writeTo(output); - } - - private int memoizedSerializedSize = -1; - public int getSerializedSize() { - int size = memoizedSerializedSize; - if (size != -1) return size; - - size = 0; - for (int i = 0; i < topicBrokers_.size(); i++) { - size += com.google.protobuf.CodedOutputStream - .computeMessageSize(1, topicBrokers_.get(i)); - } - if (((bitField0_ & 0x00000001) == 0x00000001)) { - size += com.google.protobuf.CodedOutputStream - .computeMessageSize(2, topicOrderConfs_); - } - for (int i = 0; i < brokers_.size(); i++) { - size += com.google.protobuf.CodedOutputStream - .computeMessageSize(3, brokers_.get(i)); - } - if (((bitField0_ & 0x00000002) == 0x00000002)) { - size += com.google.protobuf.CodedOutputStream - .computeMessageSize(4, brokerList_); - } - size += getUnknownFields().getSerializedSize(); - memoizedSerializedSize = size; - return size; } - - private static final long serialVersionUID = 0L; - @java.lang.Override - protected java.lang.Object writeReplace() - throws java.io.ObjectStreamException { - return super.writeReplace(); - } - - public static com.alibaba.rocketmq.common.protocol.MQProtos.TopicRuntimeInfo parseFrom( - com.google.protobuf.ByteString data) - throws com.google.protobuf.InvalidProtocolBufferException { - return newBuilder().mergeFrom(data).buildParsed(); - } - public static com.alibaba.rocketmq.common.protocol.MQProtos.TopicRuntimeInfo parseFrom( - com.google.protobuf.ByteString data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return newBuilder().mergeFrom(data, extensionRegistry) - .buildParsed(); - } - public static com.alibaba.rocketmq.common.protocol.MQProtos.TopicRuntimeInfo parseFrom(byte[] data) - throws com.google.protobuf.InvalidProtocolBufferException { - return newBuilder().mergeFrom(data).buildParsed(); - } - public static com.alibaba.rocketmq.common.protocol.MQProtos.TopicRuntimeInfo parseFrom( - byte[] data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return newBuilder().mergeFrom(data, extensionRegistry) - .buildParsed(); - } - public static com.alibaba.rocketmq.common.protocol.MQProtos.TopicRuntimeInfo parseFrom(java.io.InputStream input) - throws java.io.IOException { - return newBuilder().mergeFrom(input).buildParsed(); - } - public static com.alibaba.rocketmq.common.protocol.MQProtos.TopicRuntimeInfo parseFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return newBuilder().mergeFrom(input, extensionRegistry) - .buildParsed(); - } - public static com.alibaba.rocketmq.common.protocol.MQProtos.TopicRuntimeInfo parseDelimitedFrom(java.io.InputStream input) - throws java.io.IOException { - Builder builder = newBuilder(); - if (builder.mergeDelimitedFrom(input)) { - return builder.buildParsed(); - } else { - return null; - } - } - public static com.alibaba.rocketmq.common.protocol.MQProtos.TopicRuntimeInfo parseDelimitedFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - Builder builder = newBuilder(); - if (builder.mergeDelimitedFrom(input, extensionRegistry)) { - return builder.buildParsed(); - } else { - return null; - } - } - public static com.alibaba.rocketmq.common.protocol.MQProtos.TopicRuntimeInfo parseFrom( - com.google.protobuf.CodedInputStream input) - throws java.io.IOException { - return newBuilder().mergeFrom(input).buildParsed(); - } - public static com.alibaba.rocketmq.common.protocol.MQProtos.TopicRuntimeInfo parseFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return newBuilder().mergeFrom(input, extensionRegistry) - .buildParsed(); - } - - public static Builder newBuilder() { return Builder.create(); } - public Builder newBuilderForType() { return newBuilder(); } - public static Builder newBuilder(com.alibaba.rocketmq.common.protocol.MQProtos.TopicRuntimeInfo prototype) { - return newBuilder().mergeFrom(prototype); - } - public Builder toBuilder() { return newBuilder(this); } - - @java.lang.Override - protected Builder newBuilderForType( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - Builder builder = new Builder(parent); - return builder; - } - public static final class Builder extends - com.google.protobuf.GeneratedMessage.Builder - implements com.alibaba.rocketmq.common.protocol.MQProtos.TopicRuntimeInfoOrBuilder { - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return com.alibaba.rocketmq.common.protocol.MQProtos.internal_static_rocketmq_TopicRuntimeInfo_descriptor; - } - - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return com.alibaba.rocketmq.common.protocol.MQProtos.internal_static_rocketmq_TopicRuntimeInfo_fieldAccessorTable; - } - - // Construct using com.alibaba.rocketmq.common.protocol.MQProtos.TopicRuntimeInfo.newBuilder() - private Builder() { - maybeForceBuilderInitialization(); - } - - private Builder(BuilderParent parent) { - super(parent); - maybeForceBuilderInitialization(); - } - private void maybeForceBuilderInitialization() { - if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) { - getTopicBrokersFieldBuilder(); - getTopicOrderConfsFieldBuilder(); - getBrokersFieldBuilder(); - getBrokerListFieldBuilder(); - } - } - private static Builder create() { - return new Builder(); - } - - public Builder clear() { - super.clear(); - if (topicBrokersBuilder_ == null) { - topicBrokers_ = java.util.Collections.emptyList(); - bitField0_ = (bitField0_ & ~0x00000001); - } else { - topicBrokersBuilder_.clear(); - } - if (topicOrderConfsBuilder_ == null) { - topicOrderConfs_ = com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPairList.getDefaultInstance(); - } else { - topicOrderConfsBuilder_.clear(); - } - bitField0_ = (bitField0_ & ~0x00000002); - if (brokersBuilder_ == null) { - brokers_ = java.util.Collections.emptyList(); - bitField0_ = (bitField0_ & ~0x00000004); - } else { - brokersBuilder_.clear(); - } - if (brokerListBuilder_ == null) { - brokerList_ = com.alibaba.rocketmq.remoting.protocol.RemotingProtos.StringList.getDefaultInstance(); - } else { - brokerListBuilder_.clear(); - } - bitField0_ = (bitField0_ & ~0x00000008); - return this; - } - - public Builder clone() { - return create().mergeFrom(buildPartial()); - } - - public com.google.protobuf.Descriptors.Descriptor - getDescriptorForType() { - return com.alibaba.rocketmq.common.protocol.MQProtos.TopicRuntimeInfo.getDescriptor(); - } - - public com.alibaba.rocketmq.common.protocol.MQProtos.TopicRuntimeInfo getDefaultInstanceForType() { - return com.alibaba.rocketmq.common.protocol.MQProtos.TopicRuntimeInfo.getDefaultInstance(); - } - - public com.alibaba.rocketmq.common.protocol.MQProtos.TopicRuntimeInfo build() { - com.alibaba.rocketmq.common.protocol.MQProtos.TopicRuntimeInfo result = buildPartial(); - if (!result.isInitialized()) { - throw newUninitializedMessageException(result); - } - return result; - } - - private com.alibaba.rocketmq.common.protocol.MQProtos.TopicRuntimeInfo buildParsed() - throws com.google.protobuf.InvalidProtocolBufferException { - com.alibaba.rocketmq.common.protocol.MQProtos.TopicRuntimeInfo result = buildPartial(); - if (!result.isInitialized()) { - throw newUninitializedMessageException( - result).asInvalidProtocolBufferException(); - } - return result; - } - - public com.alibaba.rocketmq.common.protocol.MQProtos.TopicRuntimeInfo buildPartial() { - com.alibaba.rocketmq.common.protocol.MQProtos.TopicRuntimeInfo result = new com.alibaba.rocketmq.common.protocol.MQProtos.TopicRuntimeInfo(this); - int from_bitField0_ = bitField0_; - int to_bitField0_ = 0; - if (topicBrokersBuilder_ == null) { - if (((bitField0_ & 0x00000001) == 0x00000001)) { - topicBrokers_ = java.util.Collections.unmodifiableList(topicBrokers_); - bitField0_ = (bitField0_ & ~0x00000001); - } - result.topicBrokers_ = topicBrokers_; - } else { - result.topicBrokers_ = topicBrokersBuilder_.build(); - } - if (((from_bitField0_ & 0x00000002) == 0x00000002)) { - to_bitField0_ |= 0x00000001; - } - if (topicOrderConfsBuilder_ == null) { - result.topicOrderConfs_ = topicOrderConfs_; - } else { - result.topicOrderConfs_ = topicOrderConfsBuilder_.build(); - } - if (brokersBuilder_ == null) { - if (((bitField0_ & 0x00000004) == 0x00000004)) { - brokers_ = java.util.Collections.unmodifiableList(brokers_); - bitField0_ = (bitField0_ & ~0x00000004); - } - result.brokers_ = brokers_; - } else { - result.brokers_ = brokersBuilder_.build(); - } - if (((from_bitField0_ & 0x00000008) == 0x00000008)) { - to_bitField0_ |= 0x00000002; - } - if (brokerListBuilder_ == null) { - result.brokerList_ = brokerList_; - } else { - result.brokerList_ = brokerListBuilder_.build(); - } - result.bitField0_ = to_bitField0_; - onBuilt(); - return result; - } - - public Builder mergeFrom(com.google.protobuf.Message other) { - if (other instanceof com.alibaba.rocketmq.common.protocol.MQProtos.TopicRuntimeInfo) { - return mergeFrom((com.alibaba.rocketmq.common.protocol.MQProtos.TopicRuntimeInfo)other); - } else { - super.mergeFrom(other); - return this; - } - } - - public Builder mergeFrom(com.alibaba.rocketmq.common.protocol.MQProtos.TopicRuntimeInfo other) { - if (other == com.alibaba.rocketmq.common.protocol.MQProtos.TopicRuntimeInfo.getDefaultInstance()) return this; - if (topicBrokersBuilder_ == null) { - if (!other.topicBrokers_.isEmpty()) { - if (topicBrokers_.isEmpty()) { - topicBrokers_ = other.topicBrokers_; - bitField0_ = (bitField0_ & ~0x00000001); - } else { - ensureTopicBrokersIsMutable(); - topicBrokers_.addAll(other.topicBrokers_); - } - onChanged(); - } - } else { - if (!other.topicBrokers_.isEmpty()) { - if (topicBrokersBuilder_.isEmpty()) { - topicBrokersBuilder_.dispose(); - topicBrokersBuilder_ = null; - topicBrokers_ = other.topicBrokers_; - bitField0_ = (bitField0_ & ~0x00000001); - topicBrokersBuilder_ = - com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders ? - getTopicBrokersFieldBuilder() : null; - } else { - topicBrokersBuilder_.addAllMessages(other.topicBrokers_); - } - } - } - if (other.hasTopicOrderConfs()) { - mergeTopicOrderConfs(other.getTopicOrderConfs()); - } - if (brokersBuilder_ == null) { - if (!other.brokers_.isEmpty()) { - if (brokers_.isEmpty()) { - brokers_ = other.brokers_; - bitField0_ = (bitField0_ & ~0x00000004); - } else { - ensureBrokersIsMutable(); - brokers_.addAll(other.brokers_); - } - onChanged(); - } - } else { - if (!other.brokers_.isEmpty()) { - if (brokersBuilder_.isEmpty()) { - brokersBuilder_.dispose(); - brokersBuilder_ = null; - brokers_ = other.brokers_; - bitField0_ = (bitField0_ & ~0x00000004); - brokersBuilder_ = - com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders ? - getBrokersFieldBuilder() : null; - } else { - brokersBuilder_.addAllMessages(other.brokers_); - } - } - } - if (other.hasBrokerList()) { - mergeBrokerList(other.getBrokerList()); - } - this.mergeUnknownFields(other.getUnknownFields()); - return this; - } - - public final boolean isInitialized() { - if (!hasTopicOrderConfs()) { - - return false; - } - if (!hasBrokerList()) { - - return false; - } - for (int i = 0; i < getTopicBrokersCount(); i++) { - if (!getTopicBrokers(i).isInitialized()) { - - return false; - } - } - if (!getTopicOrderConfs().isInitialized()) { - - return false; - } - for (int i = 0; i < getBrokersCount(); i++) { - if (!getBrokers(i).isInitialized()) { - - return false; - } + + public enum MQResponseCode { + // Broker 刷盘超时 + FLUSH_DISK_TIMEOUT(0, 10), + // Broker 同步双写,Slave不可用 + SLAVE_NOT_AVAILABLE(1, 11), + // Broker 同步双写,等待Slave应答超时 + FLUSH_SLAVE_TIMEOUT(2, 12), + // Broker 消息非法 + MESSAGE_ILLEGAL(3, 13), + // Broker, Namesrv 服务不可用,可能是正在关闭或者权限问题 + SERVICE_NOT_AVAILABLE(4, 14), + // Broker, Namesrv 版本号不支持 + VERSION_NOT_SUPPORTED(5, 15), + // Broker, Namesrv 无权限执行此操作,可能是发、收、或者其他操作 + NO_PERMISSION(6, 16), + // Broker, Topic不存在 + TOPIC_NOT_EXIST(7, 17), + // Broker, Topic已经存在,创建Topic + TOPIC_EXIST_ALREADY(8, 18), + // Broker 拉消息未找到(请求的Offset等于最大Offset,最大Offset无对应消息) + PULL_NOT_FOUND(9, 19), + // Broker 可能被过滤,或者误通知等 + PULL_RETRY_IMMEDIATELY(10, 20), + // Broker 拉消息请求的Offset不合法,太小或太大 + PULL_OFFSET_MOVED(11, 21), + // Broker 查询消息未找到 + QUERY_NOT_FOUND(12, 22), + // Broker 订阅关系解析失败 + SUBSCRIPTION_PARSE_FAILED(13, 23), + // Broker 订阅关系不存在 + SUBSCRIPTION_NOT_EXIST(14, 24), + // Broker 订阅关系不是最新的 + SUBSCRIPTION_NOT_LATEST(15, 25), + // Broker 订阅组不存在 + SUBSCRIPTION_GROUP_NOT_EXIST(16, 26), + // Producer 事务应该被提交 + TRANSACTION_SHOULD_COMMIT(17, 200), + // Producer 事务应该被回滚 + TRANSACTION_SHOULD_ROLLBACK(18, 201), + // Producer 事务状态未知 + TRANSACTION_STATE_UNKNOW(19, 202), + // Producer ProducerGroup错误 + TRANSACTION_STATE_GROUP_WRONG(20, 203), ; + // Broker 刷盘超时 + public static final int FLUSH_DISK_TIMEOUT_VALUE = 10; + // Broker 同步双写,Slave不可用 + public static final int SLAVE_NOT_AVAILABLE_VALUE = 11; + // Broker 同步双写,等待Slave应答超时 + public static final int FLUSH_SLAVE_TIMEOUT_VALUE = 12; + // Broker 消息非法 + public static final int MESSAGE_ILLEGAL_VALUE = 13; + // Broker, Namesrv 服务不可用,可能是正在关闭或者权限问题 + public static final int SERVICE_NOT_AVAILABLE_VALUE = 14; + // Broker, Namesrv 版本号不支持 + public static final int VERSION_NOT_SUPPORTED_VALUE = 15; + // Broker, Namesrv 无权限执行此操作,可能是发、收、或者其他操作 + public static final int NO_PERMISSION_VALUE = 16; + // Broker, Topic不存在 + public static final int TOPIC_NOT_EXIST_VALUE = 17; + // Broker, Topic已经存在,创建Topic + public static final int TOPIC_EXIST_ALREADY_VALUE = 18; + // Broker 拉消息未找到(请求的Offset等于最大Offset,最大Offset无对应消息) + public static final int PULL_NOT_FOUND_VALUE = 19; + // Broker 可能被过滤,或者误通知等 + public static final int PULL_RETRY_IMMEDIATELY_VALUE = 20; + // Broker 拉消息请求的Offset不合法,太小或太大 + public static final int PULL_OFFSET_MOVED_VALUE = 21; + // Broker 查询消息未找到 + public static final int QUERY_NOT_FOUND_VALUE = 22; + // Broker 订阅关系解析失败 + public static final int SUBSCRIPTION_PARSE_FAILED_VALUE = 23; + // Broker 订阅关系不存在 + public static final int SUBSCRIPTION_NOT_EXIST_VALUE = 24; + // Broker 订阅关系不是最新的 + public static final int SUBSCRIPTION_NOT_LATEST_VALUE = 25; + // Broker 订阅组不存在 + public static final int SUBSCRIPTION_GROUP_NOT_EXIST_VALUE = 26; + // Producer 事务应该被提交 + public static final int TRANSACTION_SHOULD_COMMIT_VALUE = 200; + // Producer 事务应该被回滚 + public static final int TRANSACTION_SHOULD_ROLLBACK_VALUE = 201; + // Producer 事务状态未知 + public static final int TRANSACTION_STATE_UNKNOW_VALUE = 202; + // Producer ProducerGroup错误 + public static final int TRANSACTION_STATE_GROUP_WRONG_VALUE = 203; + private final int index; + private final int value; + + + private MQResponseCode(int index, int value) { + this.index = index; + this.value = value; } - return true; - } - - public Builder mergeFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - com.google.protobuf.UnknownFieldSet.Builder unknownFields = - com.google.protobuf.UnknownFieldSet.newBuilder( - this.getUnknownFields()); - while (true) { - int tag = input.readTag(); - switch (tag) { - case 0: - this.setUnknownFields(unknownFields.build()); - onChanged(); - return this; - default: { - if (!parseUnknownField(input, unknownFields, - extensionRegistry, tag)) { - this.setUnknownFields(unknownFields.build()); - onChanged(); - return this; - } - break; - } - case 10: { - com.alibaba.rocketmq.common.protocol.MQProtos.TopicQueuePair.Builder subBuilder = com.alibaba.rocketmq.common.protocol.MQProtos.TopicQueuePair.newBuilder(); - input.readMessage(subBuilder, extensionRegistry); - addTopicBrokers(subBuilder.buildPartial()); - break; - } - case 18: { - com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPairList.Builder subBuilder = com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPairList.newBuilder(); - if (hasTopicOrderConfs()) { - subBuilder.mergeFrom(getTopicOrderConfs()); - } - input.readMessage(subBuilder, extensionRegistry); - setTopicOrderConfs(subBuilder.buildPartial()); - break; - } - case 26: { - com.alibaba.rocketmq.common.protocol.MQProtos.BrokerDataPair.Builder subBuilder = com.alibaba.rocketmq.common.protocol.MQProtos.BrokerDataPair.newBuilder(); - input.readMessage(subBuilder, extensionRegistry); - addBrokers(subBuilder.buildPartial()); - break; - } - case 34: { - com.alibaba.rocketmq.remoting.protocol.RemotingProtos.StringList.Builder subBuilder = com.alibaba.rocketmq.remoting.protocol.RemotingProtos.StringList.newBuilder(); - if (hasBrokerList()) { - subBuilder.mergeFrom(getBrokerList()); - } - input.readMessage(subBuilder, extensionRegistry); - setBrokerList(subBuilder.buildPartial()); - break; + + + public static MQResponseCode valueOf(int value) { + switch (value) { + case 10: + return FLUSH_DISK_TIMEOUT; + case 11: + return SLAVE_NOT_AVAILABLE; + case 12: + return FLUSH_SLAVE_TIMEOUT; + case 13: + return MESSAGE_ILLEGAL; + case 14: + return SERVICE_NOT_AVAILABLE; + case 15: + return VERSION_NOT_SUPPORTED; + case 16: + return NO_PERMISSION; + case 17: + return TOPIC_NOT_EXIST; + case 18: + return TOPIC_EXIST_ALREADY; + case 19: + return PULL_NOT_FOUND; + case 20: + return PULL_RETRY_IMMEDIATELY; + case 21: + return PULL_OFFSET_MOVED; + case 22: + return QUERY_NOT_FOUND; + case 23: + return SUBSCRIPTION_PARSE_FAILED; + case 24: + return SUBSCRIPTION_NOT_EXIST; + case 25: + return SUBSCRIPTION_NOT_LATEST; + case 26: + return SUBSCRIPTION_GROUP_NOT_EXIST; + case 200: + return TRANSACTION_SHOULD_COMMIT; + case 201: + return TRANSACTION_SHOULD_ROLLBACK; + case 202: + return TRANSACTION_STATE_UNKNOW; + case 203: + return TRANSACTION_STATE_GROUP_WRONG; + default: + return null; } - } - } - } - - private int bitField0_; - - // repeated .rocketmq.TopicQueuePair topicBrokers = 1; - private java.util.List topicBrokers_ = - java.util.Collections.emptyList(); - private void ensureTopicBrokersIsMutable() { - if (!((bitField0_ & 0x00000001) == 0x00000001)) { - topicBrokers_ = new java.util.ArrayList(topicBrokers_); - bitField0_ |= 0x00000001; - } - } - - private com.google.protobuf.RepeatedFieldBuilder< - com.alibaba.rocketmq.common.protocol.MQProtos.TopicQueuePair, com.alibaba.rocketmq.common.protocol.MQProtos.TopicQueuePair.Builder, com.alibaba.rocketmq.common.protocol.MQProtos.TopicQueuePairOrBuilder> topicBrokersBuilder_; - - public java.util.List getTopicBrokersList() { - if (topicBrokersBuilder_ == null) { - return java.util.Collections.unmodifiableList(topicBrokers_); - } else { - return topicBrokersBuilder_.getMessageList(); - } - } - public int getTopicBrokersCount() { - if (topicBrokersBuilder_ == null) { - return topicBrokers_.size(); - } else { - return topicBrokersBuilder_.getCount(); - } - } - public com.alibaba.rocketmq.common.protocol.MQProtos.TopicQueuePair getTopicBrokers(int index) { - if (topicBrokersBuilder_ == null) { - return topicBrokers_.get(index); - } else { - return topicBrokersBuilder_.getMessage(index); - } - } - public Builder setTopicBrokers( - int index, com.alibaba.rocketmq.common.protocol.MQProtos.TopicQueuePair value) { - if (topicBrokersBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - ensureTopicBrokersIsMutable(); - topicBrokers_.set(index, value); - onChanged(); - } else { - topicBrokersBuilder_.setMessage(index, value); - } - return this; - } - public Builder setTopicBrokers( - int index, com.alibaba.rocketmq.common.protocol.MQProtos.TopicQueuePair.Builder builderForValue) { - if (topicBrokersBuilder_ == null) { - ensureTopicBrokersIsMutable(); - topicBrokers_.set(index, builderForValue.build()); - onChanged(); - } else { - topicBrokersBuilder_.setMessage(index, builderForValue.build()); - } - return this; - } - public Builder addTopicBrokers(com.alibaba.rocketmq.common.protocol.MQProtos.TopicQueuePair value) { - if (topicBrokersBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - ensureTopicBrokersIsMutable(); - topicBrokers_.add(value); - onChanged(); - } else { - topicBrokersBuilder_.addMessage(value); - } - return this; - } - public Builder addTopicBrokers( - int index, com.alibaba.rocketmq.common.protocol.MQProtos.TopicQueuePair value) { - if (topicBrokersBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - ensureTopicBrokersIsMutable(); - topicBrokers_.add(index, value); - onChanged(); - } else { - topicBrokersBuilder_.addMessage(index, value); - } - return this; - } - public Builder addTopicBrokers( - com.alibaba.rocketmq.common.protocol.MQProtos.TopicQueuePair.Builder builderForValue) { - if (topicBrokersBuilder_ == null) { - ensureTopicBrokersIsMutable(); - topicBrokers_.add(builderForValue.build()); - onChanged(); - } else { - topicBrokersBuilder_.addMessage(builderForValue.build()); - } - return this; - } - public Builder addTopicBrokers( - int index, com.alibaba.rocketmq.common.protocol.MQProtos.TopicQueuePair.Builder builderForValue) { - if (topicBrokersBuilder_ == null) { - ensureTopicBrokersIsMutable(); - topicBrokers_.add(index, builderForValue.build()); - onChanged(); - } else { - topicBrokersBuilder_.addMessage(index, builderForValue.build()); - } - return this; - } - public Builder addAllTopicBrokers( - java.lang.Iterable values) { - if (topicBrokersBuilder_ == null) { - ensureTopicBrokersIsMutable(); - super.addAll(values, topicBrokers_); - onChanged(); - } else { - topicBrokersBuilder_.addAllMessages(values); - } - return this; - } - public Builder clearTopicBrokers() { - if (topicBrokersBuilder_ == null) { - topicBrokers_ = java.util.Collections.emptyList(); - bitField0_ = (bitField0_ & ~0x00000001); - onChanged(); - } else { - topicBrokersBuilder_.clear(); - } - return this; - } - public Builder removeTopicBrokers(int index) { - if (topicBrokersBuilder_ == null) { - ensureTopicBrokersIsMutable(); - topicBrokers_.remove(index); - onChanged(); - } else { - topicBrokersBuilder_.remove(index); - } - return this; - } - public com.alibaba.rocketmq.common.protocol.MQProtos.TopicQueuePair.Builder getTopicBrokersBuilder( - int index) { - return getTopicBrokersFieldBuilder().getBuilder(index); - } - public com.alibaba.rocketmq.common.protocol.MQProtos.TopicQueuePairOrBuilder getTopicBrokersOrBuilder( - int index) { - if (topicBrokersBuilder_ == null) { - return topicBrokers_.get(index); } else { - return topicBrokersBuilder_.getMessageOrBuilder(index); - } - } - public java.util.List - getTopicBrokersOrBuilderList() { - if (topicBrokersBuilder_ != null) { - return topicBrokersBuilder_.getMessageOrBuilderList(); - } else { - return java.util.Collections.unmodifiableList(topicBrokers_); - } - } - public com.alibaba.rocketmq.common.protocol.MQProtos.TopicQueuePair.Builder addTopicBrokersBuilder() { - return getTopicBrokersFieldBuilder().addBuilder( - com.alibaba.rocketmq.common.protocol.MQProtos.TopicQueuePair.getDefaultInstance()); - } - public com.alibaba.rocketmq.common.protocol.MQProtos.TopicQueuePair.Builder addTopicBrokersBuilder( - int index) { - return getTopicBrokersFieldBuilder().addBuilder( - index, com.alibaba.rocketmq.common.protocol.MQProtos.TopicQueuePair.getDefaultInstance()); - } - public java.util.List - getTopicBrokersBuilderList() { - return getTopicBrokersFieldBuilder().getBuilderList(); - } - private com.google.protobuf.RepeatedFieldBuilder< - com.alibaba.rocketmq.common.protocol.MQProtos.TopicQueuePair, com.alibaba.rocketmq.common.protocol.MQProtos.TopicQueuePair.Builder, com.alibaba.rocketmq.common.protocol.MQProtos.TopicQueuePairOrBuilder> - getTopicBrokersFieldBuilder() { - if (topicBrokersBuilder_ == null) { - topicBrokersBuilder_ = new com.google.protobuf.RepeatedFieldBuilder< - com.alibaba.rocketmq.common.protocol.MQProtos.TopicQueuePair, com.alibaba.rocketmq.common.protocol.MQProtos.TopicQueuePair.Builder, com.alibaba.rocketmq.common.protocol.MQProtos.TopicQueuePairOrBuilder>( - topicBrokers_, - ((bitField0_ & 0x00000001) == 0x00000001), - getParentForChildren(), - isClean()); - topicBrokers_ = null; - } - return topicBrokersBuilder_; - } - - // required .remoting.NVPairList topicOrderConfs = 2; - private com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPairList topicOrderConfs_ = com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPairList.getDefaultInstance(); - private com.google.protobuf.SingleFieldBuilder< - com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPairList, com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPairList.Builder, com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPairListOrBuilder> topicOrderConfsBuilder_; - public boolean hasTopicOrderConfs() { - return ((bitField0_ & 0x00000002) == 0x00000002); - } - public com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPairList getTopicOrderConfs() { - if (topicOrderConfsBuilder_ == null) { - return topicOrderConfs_; - } else { - return topicOrderConfsBuilder_.getMessage(); } - } - public Builder setTopicOrderConfs(com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPairList value) { - if (topicOrderConfsBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - topicOrderConfs_ = value; - onChanged(); - } else { - topicOrderConfsBuilder_.setMessage(value); - } - bitField0_ |= 0x00000002; - return this; - } - public Builder setTopicOrderConfs( - com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPairList.Builder builderForValue) { - if (topicOrderConfsBuilder_ == null) { - topicOrderConfs_ = builderForValue.build(); - onChanged(); - } else { - topicOrderConfsBuilder_.setMessage(builderForValue.build()); - } - bitField0_ |= 0x00000002; - return this; - } - public Builder mergeTopicOrderConfs(com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPairList value) { - if (topicOrderConfsBuilder_ == null) { - if (((bitField0_ & 0x00000002) == 0x00000002) && - topicOrderConfs_ != com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPairList.getDefaultInstance()) { - topicOrderConfs_ = - com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPairList.newBuilder(topicOrderConfs_).mergeFrom(value).buildPartial(); - } else { - topicOrderConfs_ = value; - } - onChanged(); - } else { - topicOrderConfsBuilder_.mergeFrom(value); - } - bitField0_ |= 0x00000002; - return this; - } - public Builder clearTopicOrderConfs() { - if (topicOrderConfsBuilder_ == null) { - topicOrderConfs_ = com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPairList.getDefaultInstance(); - onChanged(); - } else { - topicOrderConfsBuilder_.clear(); - } - bitField0_ = (bitField0_ & ~0x00000002); - return this; - } - public com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPairList.Builder getTopicOrderConfsBuilder() { - bitField0_ |= 0x00000002; - onChanged(); - return getTopicOrderConfsFieldBuilder().getBuilder(); - } - public com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPairListOrBuilder getTopicOrderConfsOrBuilder() { - if (topicOrderConfsBuilder_ != null) { - return topicOrderConfsBuilder_.getMessageOrBuilder(); - } else { - return topicOrderConfs_; - } - } - private com.google.protobuf.SingleFieldBuilder< - com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPairList, com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPairList.Builder, com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPairListOrBuilder> - getTopicOrderConfsFieldBuilder() { - if (topicOrderConfsBuilder_ == null) { - topicOrderConfsBuilder_ = new com.google.protobuf.SingleFieldBuilder< - com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPairList, com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPairList.Builder, com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPairListOrBuilder>( - topicOrderConfs_, - getParentForChildren(), - isClean()); - topicOrderConfs_ = null; - } - return topicOrderConfsBuilder_; - } - - // repeated .rocketmq.BrokerDataPair brokers = 3; - private java.util.List brokers_ = - java.util.Collections.emptyList(); - private void ensureBrokersIsMutable() { - if (!((bitField0_ & 0x00000004) == 0x00000004)) { - brokers_ = new java.util.ArrayList(brokers_); - bitField0_ |= 0x00000004; - } - } - - private com.google.protobuf.RepeatedFieldBuilder< - com.alibaba.rocketmq.common.protocol.MQProtos.BrokerDataPair, com.alibaba.rocketmq.common.protocol.MQProtos.BrokerDataPair.Builder, com.alibaba.rocketmq.common.protocol.MQProtos.BrokerDataPairOrBuilder> brokersBuilder_; - - public java.util.List getBrokersList() { - if (brokersBuilder_ == null) { - return java.util.Collections.unmodifiableList(brokers_); - } else { - return brokersBuilder_.getMessageList(); - } - } - public int getBrokersCount() { - if (brokersBuilder_ == null) { - return brokers_.size(); - } else { - return brokersBuilder_.getCount(); - } - } - public com.alibaba.rocketmq.common.protocol.MQProtos.BrokerDataPair getBrokers(int index) { - if (brokersBuilder_ == null) { - return brokers_.get(index); - } else { - return brokersBuilder_.getMessage(index); - } - } - public Builder setBrokers( - int index, com.alibaba.rocketmq.common.protocol.MQProtos.BrokerDataPair value) { - if (brokersBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - ensureBrokersIsMutable(); - brokers_.set(index, value); - onChanged(); - } else { - brokersBuilder_.setMessage(index, value); - } - return this; - } - public Builder setBrokers( - int index, com.alibaba.rocketmq.common.protocol.MQProtos.BrokerDataPair.Builder builderForValue) { - if (brokersBuilder_ == null) { - ensureBrokersIsMutable(); - brokers_.set(index, builderForValue.build()); - onChanged(); - } else { - brokersBuilder_.setMessage(index, builderForValue.build()); - } - return this; - } - public Builder addBrokers(com.alibaba.rocketmq.common.protocol.MQProtos.BrokerDataPair value) { - if (brokersBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - ensureBrokersIsMutable(); - brokers_.add(value); - onChanged(); - } else { - brokersBuilder_.addMessage(value); - } - return this; - } - public Builder addBrokers( - int index, com.alibaba.rocketmq.common.protocol.MQProtos.BrokerDataPair value) { - if (brokersBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - ensureBrokersIsMutable(); - brokers_.add(index, value); - onChanged(); - } else { - brokersBuilder_.addMessage(index, value); - } - return this; - } - public Builder addBrokers( - com.alibaba.rocketmq.common.protocol.MQProtos.BrokerDataPair.Builder builderForValue) { - if (brokersBuilder_ == null) { - ensureBrokersIsMutable(); - brokers_.add(builderForValue.build()); - onChanged(); - } else { - brokersBuilder_.addMessage(builderForValue.build()); - } - return this; - } - public Builder addBrokers( - int index, com.alibaba.rocketmq.common.protocol.MQProtos.BrokerDataPair.Builder builderForValue) { - if (brokersBuilder_ == null) { - ensureBrokersIsMutable(); - brokers_.add(index, builderForValue.build()); - onChanged(); - } else { - brokersBuilder_.addMessage(index, builderForValue.build()); - } - return this; - } - public Builder addAllBrokers( - java.lang.Iterable values) { - if (brokersBuilder_ == null) { - ensureBrokersIsMutable(); - super.addAll(values, brokers_); - onChanged(); - } else { - brokersBuilder_.addAllMessages(values); - } - return this; - } - public Builder clearBrokers() { - if (brokersBuilder_ == null) { - brokers_ = java.util.Collections.emptyList(); - bitField0_ = (bitField0_ & ~0x00000004); - onChanged(); - } else { - brokersBuilder_.clear(); - } - return this; - } - public Builder removeBrokers(int index) { - if (brokersBuilder_ == null) { - ensureBrokersIsMutable(); - brokers_.remove(index); - onChanged(); - } else { - brokersBuilder_.remove(index); - } - return this; - } - public com.alibaba.rocketmq.common.protocol.MQProtos.BrokerDataPair.Builder getBrokersBuilder( - int index) { - return getBrokersFieldBuilder().getBuilder(index); - } - public com.alibaba.rocketmq.common.protocol.MQProtos.BrokerDataPairOrBuilder getBrokersOrBuilder( - int index) { - if (brokersBuilder_ == null) { - return brokers_.get(index); } else { - return brokersBuilder_.getMessageOrBuilder(index); - } - } - public java.util.List - getBrokersOrBuilderList() { - if (brokersBuilder_ != null) { - return brokersBuilder_.getMessageOrBuilderList(); - } else { - return java.util.Collections.unmodifiableList(brokers_); - } - } - public com.alibaba.rocketmq.common.protocol.MQProtos.BrokerDataPair.Builder addBrokersBuilder() { - return getBrokersFieldBuilder().addBuilder( - com.alibaba.rocketmq.common.protocol.MQProtos.BrokerDataPair.getDefaultInstance()); - } - public com.alibaba.rocketmq.common.protocol.MQProtos.BrokerDataPair.Builder addBrokersBuilder( - int index) { - return getBrokersFieldBuilder().addBuilder( - index, com.alibaba.rocketmq.common.protocol.MQProtos.BrokerDataPair.getDefaultInstance()); - } - public java.util.List - getBrokersBuilderList() { - return getBrokersFieldBuilder().getBuilderList(); - } - private com.google.protobuf.RepeatedFieldBuilder< - com.alibaba.rocketmq.common.protocol.MQProtos.BrokerDataPair, com.alibaba.rocketmq.common.protocol.MQProtos.BrokerDataPair.Builder, com.alibaba.rocketmq.common.protocol.MQProtos.BrokerDataPairOrBuilder> - getBrokersFieldBuilder() { - if (brokersBuilder_ == null) { - brokersBuilder_ = new com.google.protobuf.RepeatedFieldBuilder< - com.alibaba.rocketmq.common.protocol.MQProtos.BrokerDataPair, com.alibaba.rocketmq.common.protocol.MQProtos.BrokerDataPair.Builder, com.alibaba.rocketmq.common.protocol.MQProtos.BrokerDataPairOrBuilder>( - brokers_, - ((bitField0_ & 0x00000004) == 0x00000004), - getParentForChildren(), - isClean()); - brokers_ = null; - } - return brokersBuilder_; - } - - // required .remoting.StringList brokerList = 4; - private com.alibaba.rocketmq.remoting.protocol.RemotingProtos.StringList brokerList_ = com.alibaba.rocketmq.remoting.protocol.RemotingProtos.StringList.getDefaultInstance(); - private com.google.protobuf.SingleFieldBuilder< - com.alibaba.rocketmq.remoting.protocol.RemotingProtos.StringList, com.alibaba.rocketmq.remoting.protocol.RemotingProtos.StringList.Builder, com.alibaba.rocketmq.remoting.protocol.RemotingProtos.StringListOrBuilder> brokerListBuilder_; - public boolean hasBrokerList() { - return ((bitField0_ & 0x00000008) == 0x00000008); - } - public com.alibaba.rocketmq.remoting.protocol.RemotingProtos.StringList getBrokerList() { - if (brokerListBuilder_ == null) { - return brokerList_; - } else { - return brokerListBuilder_.getMessage(); - } - } - public Builder setBrokerList(com.alibaba.rocketmq.remoting.protocol.RemotingProtos.StringList value) { - if (brokerListBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - brokerList_ = value; - onChanged(); - } else { - brokerListBuilder_.setMessage(value); - } - bitField0_ |= 0x00000008; - return this; - } - public Builder setBrokerList( - com.alibaba.rocketmq.remoting.protocol.RemotingProtos.StringList.Builder builderForValue) { - if (brokerListBuilder_ == null) { - brokerList_ = builderForValue.build(); - onChanged(); - } else { - brokerListBuilder_.setMessage(builderForValue.build()); - } - bitField0_ |= 0x00000008; - return this; - } - public Builder mergeBrokerList(com.alibaba.rocketmq.remoting.protocol.RemotingProtos.StringList value) { - if (brokerListBuilder_ == null) { - if (((bitField0_ & 0x00000008) == 0x00000008) && - brokerList_ != com.alibaba.rocketmq.remoting.protocol.RemotingProtos.StringList.getDefaultInstance()) { - brokerList_ = - com.alibaba.rocketmq.remoting.protocol.RemotingProtos.StringList.newBuilder(brokerList_).mergeFrom(value).buildPartial(); - } else { - brokerList_ = value; - } - onChanged(); - } else { - brokerListBuilder_.mergeFrom(value); - } - bitField0_ |= 0x00000008; - return this; - } - public Builder clearBrokerList() { - if (brokerListBuilder_ == null) { - brokerList_ = com.alibaba.rocketmq.remoting.protocol.RemotingProtos.StringList.getDefaultInstance(); - onChanged(); - } else { - brokerListBuilder_.clear(); - } - bitField0_ = (bitField0_ & ~0x00000008); - return this; - } - public com.alibaba.rocketmq.remoting.protocol.RemotingProtos.StringList.Builder getBrokerListBuilder() { - bitField0_ |= 0x00000008; - onChanged(); - return getBrokerListFieldBuilder().getBuilder(); - } - public com.alibaba.rocketmq.remoting.protocol.RemotingProtos.StringListOrBuilder getBrokerListOrBuilder() { - if (brokerListBuilder_ != null) { - return brokerListBuilder_.getMessageOrBuilder(); - } else { - return brokerList_; + + + public final int getNumber() { + return value; } - } - private com.google.protobuf.SingleFieldBuilder< - com.alibaba.rocketmq.remoting.protocol.RemotingProtos.StringList, com.alibaba.rocketmq.remoting.protocol.RemotingProtos.StringList.Builder, com.alibaba.rocketmq.remoting.protocol.RemotingProtos.StringListOrBuilder> - getBrokerListFieldBuilder() { - if (brokerListBuilder_ == null) { - brokerListBuilder_ = new com.google.protobuf.SingleFieldBuilder< - com.alibaba.rocketmq.remoting.protocol.RemotingProtos.StringList, com.alibaba.rocketmq.remoting.protocol.RemotingProtos.StringList.Builder, com.alibaba.rocketmq.remoting.protocol.RemotingProtos.StringListOrBuilder>( - brokerList_, - getParentForChildren(), - isClean()); - brokerList_ = null; + + + public int getIndex() { + return index; } - return brokerListBuilder_; - } - - // @@protoc_insertion_point(builder_scope:rocketmq.TopicRuntimeInfo) } - - static { - defaultInstance = new TopicRuntimeInfo(true); - defaultInstance.initFields(); - } - - // @@protoc_insertion_point(class_scope:rocketmq.TopicRuntimeInfo) - } - - private static com.google.protobuf.Descriptors.Descriptor - internal_static_rocketmq_BrokerInfo_descriptor; - private static - com.google.protobuf.GeneratedMessage.FieldAccessorTable - internal_static_rocketmq_BrokerInfo_fieldAccessorTable; - private static com.google.protobuf.Descriptors.Descriptor - internal_static_rocketmq_BrokerInfo_BrokerAddr_descriptor; - private static - com.google.protobuf.GeneratedMessage.FieldAccessorTable - internal_static_rocketmq_BrokerInfo_BrokerAddr_fieldAccessorTable; - private static com.google.protobuf.Descriptors.Descriptor - internal_static_rocketmq_QueueInfo_descriptor; - private static - com.google.protobuf.GeneratedMessage.FieldAccessorTable - internal_static_rocketmq_QueueInfo_fieldAccessorTable; - private static com.google.protobuf.Descriptors.Descriptor - internal_static_rocketmq_TopicRouteInfo_descriptor; - private static - com.google.protobuf.GeneratedMessage.FieldAccessorTable - internal_static_rocketmq_TopicRouteInfo_fieldAccessorTable; - private static com.google.protobuf.Descriptors.Descriptor - internal_static_rocketmq_ProducerInfo_descriptor; - private static - com.google.protobuf.GeneratedMessage.FieldAccessorTable - internal_static_rocketmq_ProducerInfo_fieldAccessorTable; - private static com.google.protobuf.Descriptors.Descriptor - internal_static_rocketmq_SubscriptionInfo_descriptor; - private static - com.google.protobuf.GeneratedMessage.FieldAccessorTable - internal_static_rocketmq_SubscriptionInfo_fieldAccessorTable; - private static com.google.protobuf.Descriptors.Descriptor - internal_static_rocketmq_ConsumerInfo_descriptor; - private static - com.google.protobuf.GeneratedMessage.FieldAccessorTable - internal_static_rocketmq_ConsumerInfo_fieldAccessorTable; - private static com.google.protobuf.Descriptors.Descriptor - internal_static_rocketmq_HeartbeatInfo_descriptor; - private static - com.google.protobuf.GeneratedMessage.FieldAccessorTable - internal_static_rocketmq_HeartbeatInfo_fieldAccessorTable; - private static com.google.protobuf.Descriptors.Descriptor - internal_static_rocketmq_TopicQueuePair_descriptor; - private static - com.google.protobuf.GeneratedMessage.FieldAccessorTable - internal_static_rocketmq_TopicQueuePair_fieldAccessorTable; - private static com.google.protobuf.Descriptors.Descriptor - internal_static_rocketmq_BrokerDataPair_descriptor; - private static - com.google.protobuf.GeneratedMessage.FieldAccessorTable - internal_static_rocketmq_BrokerDataPair_fieldAccessorTable; - private static com.google.protobuf.Descriptors.Descriptor - internal_static_rocketmq_TopicRuntimeInfo_descriptor; - private static - com.google.protobuf.GeneratedMessage.FieldAccessorTable - internal_static_rocketmq_TopicRuntimeInfo_fieldAccessorTable; - - public static com.google.protobuf.Descriptors.FileDescriptor - getDescriptor() { - return descriptor; - } - private static com.google.protobuf.Descriptors.FileDescriptor - descriptor; - static { - java.lang.String[] descriptorData = { - "\n\010mq.proto\022\010rocketmq\032\016remoting.proto\"~\n\n" + - "BrokerInfo\022\022\n\nbrokerName\030\001 \002(\t\0224\n\013broker" + - "Addrs\030\002 \003(\0132\037.rocketmq.BrokerInfo.Broker" + - "Addr\032&\n\nBrokerAddr\022\n\n\002id\030\001 \002(\003\022\014\n\004addr\030\002" + - " \002(\t\"\\\n\tQueueInfo\022\022\n\nbrokerName\030\001 \002(\t\022\025\n" + - "\rreadQueueNums\030\002 \002(\005\022\026\n\016writeQueueNums\030\003" + - " \002(\005\022\014\n\004perm\030\004 \002(\005\"|\n\016TopicRouteInfo\022\'\n\n" + - "queueInfos\030\001 \003(\0132\023.rocketmq.QueueInfo\022)\n" + - "\013brokerInfos\030\002 \003(\0132\024.rocketmq.BrokerInfo" + - "\022\026\n\016orderTopicConf\030\003 \001(\t\"!\n\014ProducerInfo", - "\022\021\n\tgroupName\030\001 \002(\t\"_\n\020SubscriptionInfo\022" + - "\r\n\005topic\030\001 \002(\t\022\021\n\tsubString\030\002 \002(\t\022\021\n\tsub" + - "Numfmt\030\003 \002(\t\022\026\n\016hasAndOperator\030\004 \002(\010\"\203\001\n" + - "\014ConsumerInfo\022\021\n\tgroupName\030\001 \002(\t\022\023\n\013cons" + - "umeType\030\002 \002(\t\022\024\n\014messageModel\030\003 \002(\t\0225\n\021s" + - "ubscriptionInfos\030\004 \003(\0132\032.rocketmq.Subscr" + - "iptionInfo\"\177\n\rHeartbeatInfo\022\020\n\010clientID\030" + - "\001 \002(\t\022-\n\rproducerInfos\030\002 \003(\0132\026.rocketmq." + - "ProducerInfo\022-\n\rconsumerInfos\030\003 \003(\0132\026.ro" + - "cketmq.ConsumerInfo\"G\n\016TopicQueuePair\022\r\n", - "\005topic\030\001 \002(\t\022&\n\tqueueInfo\030\002 \003(\0132\023.rocket" + - "mq.QueueInfo\"N\n\016BrokerDataPair\022\022\n\nbroker" + - "Name\030\001 \002(\t\022(\n\nbrokerInfo\030\002 \002(\0132\024.rocketm" + - "q.BrokerInfo\"\306\001\n\020TopicRuntimeInfo\022.\n\014top" + - "icBrokers\030\001 \003(\0132\030.rocketmq.TopicQueuePai" + - "r\022-\n\017topicOrderConfs\030\002 \002(\0132\024.remoting.NV" + - "PairList\022)\n\007brokers\030\003 \003(\0132\030.rocketmq.Bro" + - "kerDataPair\022(\n\nbrokerList\030\004 \002(\0132\024.remoti" + - "ng.StringList*\251\010\n\rMQRequestCode\022\020\n\014SEND_" + - "MESSAGE\020\n\022\020\n\014PULL_MESSAGE\020\013\022\021\n\rQUERY_MES", - "SAGE\020\014\022\027\n\023QUERY_BROKER_OFFSET\020\r\022\031\n\025QUERY" + - "_CONSUMER_OFFSET\020\016\022\032\n\026UPDATE_CONSUMER_OF" + - "FSET\020\017\022\033\n\027UPDATE_AND_CREATE_TOPIC\020\021\022\020\n\014D" + - "ELETE_TOPIC\020\023\022\030\n\024GET_ALL_TOPIC_CONFIG\020\025\022" + - "\031\n\025GET_TOPIC_CONFIG_LIST\020\026\022\027\n\023GET_TOPIC_" + - "NAME_LIST\020\027\022\034\n\030PULL_ALL_CONSUMER_OFFSET\020" + - "\030\022\030\n\024UPDATE_BROKER_CONFIG\020\031\022\025\n\021GET_BROKE" + - "R_CONFIG\020\032\022\030\n\024TRIGGER_DELETE_FILES\020\033\022\033\n\027" + - "GET_BROKER_RUNTIME_INFO\020\034\022\036\n\032SEARCH_OFFS" + - "ET_BY_TIMESTAMP\020\035\022\022\n\016GET_MAX_OFFSET\020\036\022\022\n", - "\016GET_MIN_OFFSET\020\037\022\036\n\032GET_EARLIEST_MSG_ST" + - "ORETIME\020 \022\026\n\022VIEW_MESSAGE_BY_ID\020!\022\016\n\nHEA" + - "RT_BEAT\020\"\022\025\n\021UNREGISTER_CLIENT\020#\022\032\n\026CONS" + - "UMER_SEND_MSG_BACK\020$\022\023\n\017END_TRANSACTION\020" + - "%\022\033\n\027CHECK_TRANSACTION_STATE\020&\022\023\n\017REGIST" + - "ER_BROKER\020d\022\025\n\021UNREGISTER_BROKER\020e\022\023\n\017GE" + - "T_BROKER_LIST\020f\022\030\n\024REGISTER_ORDER_TOPIC\020" + - "g\022\032\n\026UNREGISTER_ORDER_TOPIC\020h\022\030\n\024GET_ORD" + - "ER_TOPIC_LIST\020i\022\031\n\025UPDATE_NAMESRV_CONFIG" + - "\020j\022\026\n\022GET_NAMESRV_CONFIG\020k\022\034\n\030GET_NAMESR", - "V_RUNTIME_INFO\020l\022\032\n\026GET_ROUTEINTO_BY_TOP" + - "IC\020m\022\035\n\031SYNC_NAMESRV_RUNTIME_CONF\020n\022\032\n\026R" + - "EGISTER_BROKER_SINGLE\020o\022\034\n\030UNREGISTER_BR" + - "OKER_SINGLE\020p\022\037\n\033REGISTER_ORDER_TOPIC_SI" + - "NGLE\020q\022!\n\035UNREGISTER_ORDER_TOPIC_SINGLE\020" + - "r*\313\005\n\016MQResponseCode\022\026\n\022FLUSH_DISK_TIMEO" + - "UT\020\n\022\027\n\023SLAVE_NOT_AVAILABLE\020\013\022\027\n\023FLUSH_S" + - "LAVE_TIMEOUT\020\014\022\023\n\017MESSAGE_ILLEGAL\020\r\022\031\n\025S" + - "ERVICE_NOT_AVAILABLE\020\016\022\031\n\025VERSION_NOT_SU" + - "PPORTED\020\017\022\021\n\rNO_PERMISSION\020\020\022\023\n\017TOPIC_NO", - "T_EXIST\020\021\022\027\n\023TOPIC_EXIST_ALREADY\020\022\022\022\n\016PU" + - "LL_NOT_FOUND\020\023\022\032\n\026PULL_RETRY_IMMEDIATELY" + - "\020\024\022\025\n\021PULL_OFFSET_MOVED\020\025\022\023\n\017QUERY_NOT_F" + - "OUND\020\026\022\027\n\023DELETE_INVALID_CONF\020d\022\022\n\016NOT_M" + - "ERGE_CONF\020e\022\030\n\024REGISTER_BROKER_FAIL\020f\022\033\n" + - "\027REGISTER_BROKER_TIMEOUT\020g\022\035\n\031REGISTER_O" + - "RDER_TOPIC_FAIL\020h\022 \n\034REGISTER_ORDER_TOPI" + - "C_TIMEOUT\020i\022\032\n\026UNREGISTER_BROKER_FAIL\020j\022" + - "\035\n\031UNREGISTER_BROKER_TIMEOUT\020k\022\"\n\036UNREGI" + - "STER_ORDER_TOPIC_TIMEOUT\020l\022\036\n\031TRANSACTIO", - "N_SHOULD_COMMIT\020\310\001\022 \n\033TRANSACTION_SHOULD" + - "_ROLLBACK\020\311\001\022\035\n\030TRANSACTION_STATE_UNKNOW" + - "\020\312\001\022\"\n\035TRANSACTION_STATE_GROUP_WRONG\020\313\001B" + - "2\n$com.alibaba.rocketmq.common.protocolB" + - "\010MQProtosH\001" - }; - com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner = - new com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner() { - public com.google.protobuf.ExtensionRegistry assignDescriptors( - com.google.protobuf.Descriptors.FileDescriptor root) { - descriptor = root; - internal_static_rocketmq_BrokerInfo_descriptor = - getDescriptor().getMessageTypes().get(0); - internal_static_rocketmq_BrokerInfo_fieldAccessorTable = new - com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_rocketmq_BrokerInfo_descriptor, - new java.lang.String[] { "BrokerName", "BrokerAddrs", }, - com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo.class, - com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo.Builder.class); - internal_static_rocketmq_BrokerInfo_BrokerAddr_descriptor = - internal_static_rocketmq_BrokerInfo_descriptor.getNestedTypes().get(0); - internal_static_rocketmq_BrokerInfo_BrokerAddr_fieldAccessorTable = new - com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_rocketmq_BrokerInfo_BrokerAddr_descriptor, - new java.lang.String[] { "Id", "Addr", }, - com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo.BrokerAddr.class, - com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo.BrokerAddr.Builder.class); - internal_static_rocketmq_QueueInfo_descriptor = - getDescriptor().getMessageTypes().get(1); - internal_static_rocketmq_QueueInfo_fieldAccessorTable = new - com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_rocketmq_QueueInfo_descriptor, - new java.lang.String[] { "BrokerName", "ReadQueueNums", "WriteQueueNums", "Perm", }, - com.alibaba.rocketmq.common.protocol.MQProtos.QueueInfo.class, - com.alibaba.rocketmq.common.protocol.MQProtos.QueueInfo.Builder.class); - internal_static_rocketmq_TopicRouteInfo_descriptor = - getDescriptor().getMessageTypes().get(2); - internal_static_rocketmq_TopicRouteInfo_fieldAccessorTable = new - com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_rocketmq_TopicRouteInfo_descriptor, - new java.lang.String[] { "QueueInfos", "BrokerInfos", "OrderTopicConf", }, - com.alibaba.rocketmq.common.protocol.MQProtos.TopicRouteInfo.class, - com.alibaba.rocketmq.common.protocol.MQProtos.TopicRouteInfo.Builder.class); - internal_static_rocketmq_ProducerInfo_descriptor = - getDescriptor().getMessageTypes().get(3); - internal_static_rocketmq_ProducerInfo_fieldAccessorTable = new - com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_rocketmq_ProducerInfo_descriptor, - new java.lang.String[] { "GroupName", }, - com.alibaba.rocketmq.common.protocol.MQProtos.ProducerInfo.class, - com.alibaba.rocketmq.common.protocol.MQProtos.ProducerInfo.Builder.class); - internal_static_rocketmq_SubscriptionInfo_descriptor = - getDescriptor().getMessageTypes().get(4); - internal_static_rocketmq_SubscriptionInfo_fieldAccessorTable = new - com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_rocketmq_SubscriptionInfo_descriptor, - new java.lang.String[] { "Topic", "SubString", "SubNumfmt", "HasAndOperator", }, - com.alibaba.rocketmq.common.protocol.MQProtos.SubscriptionInfo.class, - com.alibaba.rocketmq.common.protocol.MQProtos.SubscriptionInfo.Builder.class); - internal_static_rocketmq_ConsumerInfo_descriptor = - getDescriptor().getMessageTypes().get(5); - internal_static_rocketmq_ConsumerInfo_fieldAccessorTable = new - com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_rocketmq_ConsumerInfo_descriptor, - new java.lang.String[] { "GroupName", "ConsumeType", "MessageModel", "SubscriptionInfos", }, - com.alibaba.rocketmq.common.protocol.MQProtos.ConsumerInfo.class, - com.alibaba.rocketmq.common.protocol.MQProtos.ConsumerInfo.Builder.class); - internal_static_rocketmq_HeartbeatInfo_descriptor = - getDescriptor().getMessageTypes().get(6); - internal_static_rocketmq_HeartbeatInfo_fieldAccessorTable = new - com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_rocketmq_HeartbeatInfo_descriptor, - new java.lang.String[] { "ClientID", "ProducerInfos", "ConsumerInfos", }, - com.alibaba.rocketmq.common.protocol.MQProtos.HeartbeatInfo.class, - com.alibaba.rocketmq.common.protocol.MQProtos.HeartbeatInfo.Builder.class); - internal_static_rocketmq_TopicQueuePair_descriptor = - getDescriptor().getMessageTypes().get(7); - internal_static_rocketmq_TopicQueuePair_fieldAccessorTable = new - com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_rocketmq_TopicQueuePair_descriptor, - new java.lang.String[] { "Topic", "QueueInfo", }, - com.alibaba.rocketmq.common.protocol.MQProtos.TopicQueuePair.class, - com.alibaba.rocketmq.common.protocol.MQProtos.TopicQueuePair.Builder.class); - internal_static_rocketmq_BrokerDataPair_descriptor = - getDescriptor().getMessageTypes().get(8); - internal_static_rocketmq_BrokerDataPair_fieldAccessorTable = new - com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_rocketmq_BrokerDataPair_descriptor, - new java.lang.String[] { "BrokerName", "BrokerInfo", }, - com.alibaba.rocketmq.common.protocol.MQProtos.BrokerDataPair.class, - com.alibaba.rocketmq.common.protocol.MQProtos.BrokerDataPair.Builder.class); - internal_static_rocketmq_TopicRuntimeInfo_descriptor = - getDescriptor().getMessageTypes().get(9); - internal_static_rocketmq_TopicRuntimeInfo_fieldAccessorTable = new - com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_rocketmq_TopicRuntimeInfo_descriptor, - new java.lang.String[] { "TopicBrokers", "TopicOrderConfs", "Brokers", "BrokerList", }, - com.alibaba.rocketmq.common.protocol.MQProtos.TopicRuntimeInfo.class, - com.alibaba.rocketmq.common.protocol.MQProtos.TopicRuntimeInfo.Builder.class); - return null; - } - }; - com.google.protobuf.Descriptors.FileDescriptor - .internalBuildGeneratedFileFrom(descriptorData, - new com.google.protobuf.Descriptors.FileDescriptor[] { - com.alibaba.rocketmq.remoting.protocol.RemotingProtos.getDescriptor(), - }, assigner); - } - - // @@protoc_insertion_point(outer_class_scope) } diff --git a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/MQProtosHelper.java b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/MQProtosHelper.java index ec804c30..ae02165c 100644 --- a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/MQProtosHelper.java +++ b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/MQProtosHelper.java @@ -11,14 +11,13 @@ /** - * Э鸨 - * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * 协议辅助类 * + * @author shijia.wxr */ public class MQProtosHelper { /** - * BrokerַעᵽName Server + * 将Broker地址注册到Name Server */ public static boolean registerBrokerToNameServer(final String nsaddr, final String brokerAddr, final long timeoutMillis) { diff --git a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/body/ClusterInfo.java b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/body/ClusterInfo.java new file mode 100644 index 00000000..c1bb9dbf --- /dev/null +++ b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/body/ClusterInfo.java @@ -0,0 +1,39 @@ +package com.alibaba.rocketmq.common.protocol.body; + +import java.util.HashMap; +import java.util.Set; + +import com.alibaba.rocketmq.common.protocol.route.BrokerData; +import com.alibaba.rocketmq.remoting.protocol.RemotingSerializable; + + +/** + * 协议中传输对象,内容为集群信息 + * + * @author shijia.wxr + * @since 2013-7-16 + */ +public class ClusterInfo extends RemotingSerializable { + private HashMap brokerAddrTable; + private HashMap> clusterAddrTable; + + + public HashMap getBrokerAddrTable() { + return brokerAddrTable; + } + + + public void setBrokerAddrTable(HashMap brokerAddrTable) { + this.brokerAddrTable = brokerAddrTable; + } + + + public HashMap> getClusterAddrTable() { + return clusterAddrTable; + } + + + public void setClusterAddrTable(HashMap> clusterAddrTable) { + this.clusterAddrTable = clusterAddrTable; + } +} diff --git a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/body/Connection.java b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/body/Connection.java new file mode 100644 index 00000000..f2ca90c1 --- /dev/null +++ b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/body/Connection.java @@ -0,0 +1,57 @@ +package com.alibaba.rocketmq.common.protocol.body; + +import com.alibaba.rocketmq.remoting.protocol.LanguageCode; + + +/** + * TODO + * + * @author shijia.wxr + * @since 13-8-5 + */ +public class Connection { + private String clientId; + private String clientAddr; + private LanguageCode language; + private int version; + + + public String getClientId() { + return clientId; + } + + + public void setClientId(String clientId) { + this.clientId = clientId; + } + + + public String getClientAddr() { + return clientAddr; + } + + + public void setClientAddr(String clientAddr) { + this.clientAddr = clientAddr; + } + + + public LanguageCode getLanguage() { + return language; + } + + + public void setLanguage(LanguageCode language) { + this.language = language; + } + + + public int getVersion() { + return version; + } + + + public void setVersion(int version) { + this.version = version; + } +} diff --git a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/body/ConsumeByWho.java b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/body/ConsumeByWho.java new file mode 100644 index 00000000..c7fc20ff --- /dev/null +++ b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/body/ConsumeByWho.java @@ -0,0 +1,83 @@ +/** + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.rocketmq.common.protocol.body; + +import java.util.HashSet; + +import com.alibaba.rocketmq.remoting.protocol.RemotingSerializable; + + +/** + * @author shijia.wxr + * @since 2013-8-10 + */ +public class ConsumeByWho extends RemotingSerializable { + private HashSet consumedGroup = new HashSet(); + private HashSet notConsumedGroup = new HashSet(); + private String topic; + private int queueId; + private long offset; + + + public HashSet getConsumedGroup() { + return consumedGroup; + } + + + public void setConsumedGroup(HashSet consumedGroup) { + this.consumedGroup = consumedGroup; + } + + + public HashSet getNotConsumedGroup() { + return notConsumedGroup; + } + + + public void setNotConsumedGroup(HashSet notConsumedGroup) { + this.notConsumedGroup = notConsumedGroup; + } + + + public String getTopic() { + return topic; + } + + + public void setTopic(String topic) { + this.topic = topic; + } + + + public int getQueueId() { + return queueId; + } + + + public void setQueueId(int queueId) { + this.queueId = queueId; + } + + + public long getOffset() { + return offset; + } + + + public void setOffset(long offset) { + this.offset = offset; + } +} diff --git a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/body/ConsumerConnection.java b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/body/ConsumerConnection.java new file mode 100644 index 00000000..104149c1 --- /dev/null +++ b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/body/ConsumerConnection.java @@ -0,0 +1,88 @@ +package com.alibaba.rocketmq.common.protocol.body; + +import java.util.HashSet; +import java.util.concurrent.ConcurrentHashMap; + +import com.alibaba.rocketmq.common.consumer.ConsumeFromWhere; +import com.alibaba.rocketmq.common.protocol.heartbeat.ConsumeType; +import com.alibaba.rocketmq.common.protocol.heartbeat.MessageModel; +import com.alibaba.rocketmq.common.protocol.heartbeat.SubscriptionData; +import com.alibaba.rocketmq.remoting.protocol.RemotingSerializable; + + +/** + * TODO + * + * @author shijia.wxr + * @since 13-8-5 + */ +public class ConsumerConnection extends RemotingSerializable { + private HashSet connectionSet = new HashSet(); + private ConcurrentHashMap subscriptionTable = + new ConcurrentHashMap(); + private ConsumeType consumeType; + private MessageModel messageModel; + private ConsumeFromWhere consumeFromWhere; + + + public int computeMinVersion() { + int minVersion = Integer.MAX_VALUE; + for (Connection c : this.connectionSet) { + if (c.getVersion() < minVersion) { + minVersion = c.getVersion(); + } + } + + return minVersion; + } + + + public HashSet getConnectionSet() { + return connectionSet; + } + + + public void setConnectionSet(HashSet connectionSet) { + this.connectionSet = connectionSet; + } + + + public ConcurrentHashMap getSubscriptionTable() { + return subscriptionTable; + } + + + public void setSubscriptionTable(ConcurrentHashMap subscriptionTable) { + this.subscriptionTable = subscriptionTable; + } + + + public ConsumeType getConsumeType() { + return consumeType; + } + + + public void setConsumeType(ConsumeType consumeType) { + this.consumeType = consumeType; + } + + + public MessageModel getMessageModel() { + return messageModel; + } + + + public void setMessageModel(MessageModel messageModel) { + this.messageModel = messageModel; + } + + + public ConsumeFromWhere getConsumeFromWhere() { + return consumeFromWhere; + } + + + public void setConsumeFromWhere(ConsumeFromWhere consumeFromWhere) { + this.consumeFromWhere = consumeFromWhere; + } +} diff --git a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/body/ConsumerOffsetSerializeWrapper.java b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/body/ConsumerOffsetSerializeWrapper.java new file mode 100644 index 00000000..bf017795 --- /dev/null +++ b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/body/ConsumerOffsetSerializeWrapper.java @@ -0,0 +1,27 @@ +package com.alibaba.rocketmq.common.protocol.body; + +import java.util.concurrent.ConcurrentHashMap; + +import com.alibaba.rocketmq.remoting.protocol.RemotingSerializable; + + +/** + * Consumer消费进度,序列化包装 + * + * @author manhong.yqd + * @since 2013-8-19 + */ +public class ConsumerOffsetSerializeWrapper extends RemotingSerializable { + private ConcurrentHashMap> offsetTable = + new ConcurrentHashMap>(512); + + + public ConcurrentHashMap> getOffsetTable() { + return offsetTable; + } + + + public void setOffsetTable(ConcurrentHashMap> offsetTable) { + this.offsetTable = offsetTable; + } +} diff --git a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/body/GetConsumerStatusBody.java b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/body/GetConsumerStatusBody.java new file mode 100644 index 00000000..d5347f2d --- /dev/null +++ b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/body/GetConsumerStatusBody.java @@ -0,0 +1,40 @@ +package com.alibaba.rocketmq.common.protocol.body; + +import java.util.HashMap; +import java.util.Map; + +import com.alibaba.rocketmq.common.message.MessageQueue; +import com.alibaba.rocketmq.remoting.protocol.RemotingSerializable; + + +/** + * 查看客户端消费组的消费情况。 + * + * @author: manhong.yqd + * @since: 13-12-30 + */ +public class GetConsumerStatusBody extends RemotingSerializable { + private Map messageQueueTable = new HashMap(); + private Map> consumerTable = + new HashMap>(); + + + public Map getMessageQueueTable() { + return messageQueueTable; + } + + + public void setMessageQueueTable(Map messageQueueTable) { + this.messageQueueTable = messageQueueTable; + } + + + public Map> getConsumerTable() { + return consumerTable; + } + + + public void setConsumerTable(Map> consumerTable) { + this.consumerTable = consumerTable; + } +} diff --git a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/body/KVTable.java b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/body/KVTable.java new file mode 100644 index 00000000..c76ea974 --- /dev/null +++ b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/body/KVTable.java @@ -0,0 +1,39 @@ +/** + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.rocketmq.common.protocol.body; + +import java.util.HashMap; + +import com.alibaba.rocketmq.remoting.protocol.RemotingSerializable; + + +/** + * @author shijia.wxr + * @since 2013-8-14 + */ +public class KVTable extends RemotingSerializable { + private HashMap table = new HashMap(); + + + public HashMap getTable() { + return table; + } + + + public void setTable(HashMap table) { + this.table = table; + } +} diff --git a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/body/LockBatchRequestBody.java b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/body/LockBatchRequestBody.java new file mode 100644 index 00000000..4f9a9e76 --- /dev/null +++ b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/body/LockBatchRequestBody.java @@ -0,0 +1,48 @@ +package com.alibaba.rocketmq.common.protocol.body; + +import java.util.HashSet; +import java.util.Set; + +import com.alibaba.rocketmq.common.message.MessageQueue; +import com.alibaba.rocketmq.remoting.protocol.RemotingSerializable; + + +/** + * @author shijia.wxr + * @since 2013-6-26 + */ +public class LockBatchRequestBody extends RemotingSerializable { + private String consumerGroup; + private String clientId; + private Set mqSet = new HashSet(); + + + public String getConsumerGroup() { + return consumerGroup; + } + + + public void setConsumerGroup(String consumerGroup) { + this.consumerGroup = consumerGroup; + } + + + public String getClientId() { + return clientId; + } + + + public void setClientId(String clientId) { + this.clientId = clientId; + } + + + public Set getMqSet() { + return mqSet; + } + + + public void setMqSet(Set mqSet) { + this.mqSet = mqSet; + } +} diff --git a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/body/LockBatchResponseBody.java b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/body/LockBatchResponseBody.java new file mode 100644 index 00000000..f959ad11 --- /dev/null +++ b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/body/LockBatchResponseBody.java @@ -0,0 +1,28 @@ +package com.alibaba.rocketmq.common.protocol.body; + +import java.util.HashSet; +import java.util.Set; + +import com.alibaba.rocketmq.common.message.MessageQueue; +import com.alibaba.rocketmq.remoting.protocol.RemotingSerializable; + + +/** + * @author shijia.wxr + * @since 2013-6-26 + */ +public class LockBatchResponseBody extends RemotingSerializable { + // Lock成功的队列集合 + private Set lockOKMQSet = new HashSet(); + + + public Set getLockOKMQSet() { + return lockOKMQSet; + } + + + public void setLockOKMQSet(Set lockOKMQSet) { + this.lockOKMQSet = lockOKMQSet; + } + +} diff --git a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/body/ProducerConnection.java b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/body/ProducerConnection.java new file mode 100644 index 00000000..98fd9a7c --- /dev/null +++ b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/body/ProducerConnection.java @@ -0,0 +1,26 @@ +package com.alibaba.rocketmq.common.protocol.body; + +import java.util.HashSet; + +import com.alibaba.rocketmq.remoting.protocol.RemotingSerializable; + + +/** + * TODO + * + * @author shijia.wxr + * @since 13-8-5 + */ +public class ProducerConnection extends RemotingSerializable { + private HashSet connectionSet = new HashSet(); + + + public HashSet getConnectionSet() { + return connectionSet; + } + + + public void setConnectionSet(HashSet connectionSet) { + this.connectionSet = connectionSet; + } +} diff --git a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/body/ResetOffsetBody.java b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/body/ResetOffsetBody.java new file mode 100644 index 00000000..a1c47034 --- /dev/null +++ b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/body/ResetOffsetBody.java @@ -0,0 +1,27 @@ +package com.alibaba.rocketmq.common.protocol.body; + +import java.util.Map; + +import com.alibaba.rocketmq.common.message.MessageQueue; +import com.alibaba.rocketmq.remoting.protocol.RemotingSerializable; + + +/** + * 重置 offset 处理结果。 + * + * @author: manhong.yqd + * @since: 13-12-30 + */ +public class ResetOffsetBody extends RemotingSerializable { + private Map offsetTable; + + + public Map getOffsetTable() { + return offsetTable; + } + + + public void setOffsetTable(Map offsetTable) { + this.offsetTable = offsetTable; + } +} diff --git a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/body/SubscriptionGroupWrapper.java b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/body/SubscriptionGroupWrapper.java new file mode 100644 index 00000000..1cd3c3cf --- /dev/null +++ b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/body/SubscriptionGroupWrapper.java @@ -0,0 +1,41 @@ +package com.alibaba.rocketmq.common.protocol.body; + +import java.util.concurrent.ConcurrentHashMap; + +import com.alibaba.rocketmq.common.DataVersion; +import com.alibaba.rocketmq.common.subscription.SubscriptionGroupConfig; +import com.alibaba.rocketmq.remoting.protocol.RemotingSerializable; + + +/** + * 订阅组配置,序列化包装 + * + * @author manhong.yqd + * @since 2013-8-19 + */ +public class SubscriptionGroupWrapper extends RemotingSerializable { + private ConcurrentHashMap subscriptionGroupTable = + new ConcurrentHashMap(1024); + private DataVersion dataVersion = new DataVersion(); + + + public ConcurrentHashMap getSubscriptionGroupTable() { + return subscriptionGroupTable; + } + + + public void setSubscriptionGroupTable( + ConcurrentHashMap subscriptionGroupTable) { + this.subscriptionGroupTable = subscriptionGroupTable; + } + + + public DataVersion getDataVersion() { + return dataVersion; + } + + + public void setDataVersion(DataVersion dataVersion) { + this.dataVersion = dataVersion; + } +} diff --git a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/body/TopicConfigSerializeWrapper.java b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/body/TopicConfigSerializeWrapper.java new file mode 100644 index 00000000..0892068a --- /dev/null +++ b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/body/TopicConfigSerializeWrapper.java @@ -0,0 +1,34 @@ +package com.alibaba.rocketmq.common.protocol.body; + +import java.util.concurrent.ConcurrentHashMap; + +import com.alibaba.rocketmq.common.DataVersion; +import com.alibaba.rocketmq.common.TopicConfig; +import com.alibaba.rocketmq.remoting.protocol.RemotingSerializable; + + +public class TopicConfigSerializeWrapper extends RemotingSerializable { + private ConcurrentHashMap topicConfigTable = + new ConcurrentHashMap(); + private DataVersion dataVersion = new DataVersion(); + + + public ConcurrentHashMap getTopicConfigTable() { + return topicConfigTable; + } + + + public void setTopicConfigTable(ConcurrentHashMap topicConfigTable) { + this.topicConfigTable = topicConfigTable; + } + + + public DataVersion getDataVersion() { + return dataVersion; + } + + + public void setDataVersion(DataVersion dataVersion) { + this.dataVersion = dataVersion; + } +} diff --git a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/body/TopicList.java b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/body/TopicList.java new file mode 100644 index 00000000..01f46cae --- /dev/null +++ b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/body/TopicList.java @@ -0,0 +1,39 @@ +/** + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.rocketmq.common.protocol.body; + +import java.util.HashSet; + +import com.alibaba.rocketmq.remoting.protocol.RemotingSerializable; + + +/** + * @author shijia.wxr + * @since 2013-8-10 + */ +public class TopicList extends RemotingSerializable { + private HashSet topicList = new HashSet(); + + + public HashSet getTopicList() { + return topicList; + } + + + public void setTopicList(HashSet topicList) { + this.topicList = topicList; + } +} diff --git a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/body/UnlockBatchRequestBody.java b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/body/UnlockBatchRequestBody.java new file mode 100644 index 00000000..23960cf9 --- /dev/null +++ b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/body/UnlockBatchRequestBody.java @@ -0,0 +1,48 @@ +package com.alibaba.rocketmq.common.protocol.body; + +import java.util.HashSet; +import java.util.Set; + +import com.alibaba.rocketmq.common.message.MessageQueue; +import com.alibaba.rocketmq.remoting.protocol.RemotingSerializable; + + +/** + * @author shijia.wxr + * @since 2013-6-26 + */ +public class UnlockBatchRequestBody extends RemotingSerializable { + private String consumerGroup; + private String clientId; + private Set mqSet = new HashSet(); + + + public String getConsumerGroup() { + return consumerGroup; + } + + + public void setConsumerGroup(String consumerGroup) { + this.consumerGroup = consumerGroup; + } + + + public String getClientId() { + return clientId; + } + + + public void setClientId(String clientId) { + this.clientId = clientId; + } + + + public Set getMqSet() { + return mqSet; + } + + + public void setMqSet(Set mqSet) { + this.mqSet = mqSet; + } +} diff --git a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/generate.bat b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/generate.bat deleted file mode 100644 index 84d29858..00000000 --- a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/generate.bat +++ /dev/null @@ -1,2 +0,0 @@ -protoc.exe -I=./ --java_out=../../../../.. ./mq.proto -pause \ No newline at end of file diff --git a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/CheckTransactionStateRequestHeader.java b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/CheckTransactionStateRequestHeader.java index 7e3cd71a..705cb7aa 100644 --- a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/CheckTransactionStateRequestHeader.java +++ b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/CheckTransactionStateRequestHeader.java @@ -9,8 +9,7 @@ /** - * @author vintage.wang@gmail.com shijia.wxr@taobao.com - * + * @author shijia.wxr */ public class CheckTransactionStateRequestHeader implements CommandCustomHeader { @CFNotNull diff --git a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/CheckTransactionStateResponseHeader.java b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/CheckTransactionStateResponseHeader.java index f46a767e..1aca4635 100644 --- a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/CheckTransactionStateResponseHeader.java +++ b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/CheckTransactionStateResponseHeader.java @@ -10,8 +10,7 @@ /** - * @author vintage.wang@gmail.com shijia.wxr@taobao.com - * + * @author shijia.wxr */ public class CheckTransactionStateResponseHeader implements CommandCustomHeader { @CFNotNull @@ -22,9 +21,10 @@ public class CheckTransactionStateResponseHeader implements CommandCustomHeader private Long commitLogOffset; @CFNotNull private Integer commitOrRollback; // TransactionCommitType - // TransactionRollbackType + // TransactionRollbackType + @Override public void checkFields() throws RemotingCommandException { if (MessageSysFlag.TransactionCommitType == this.commitOrRollback) { diff --git a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/ConsumerSendMsgBackRequestHeader.java b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/ConsumerSendMsgBackRequestHeader.java new file mode 100644 index 00000000..19338d0d --- /dev/null +++ b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/ConsumerSendMsgBackRequestHeader.java @@ -0,0 +1,62 @@ +package com.alibaba.rocketmq.common.protocol.header; + +import com.alibaba.rocketmq.remoting.CommandCustomHeader; +import com.alibaba.rocketmq.remoting.annotation.CFNotNull; +import com.alibaba.rocketmq.remoting.exception.RemotingCommandException; + + +/** + * @author shijia.wxr + * @since 2013-6-18 + */ +public class ConsumerSendMsgBackRequestHeader implements CommandCustomHeader { + @CFNotNull + private Long offset; + @CFNotNull + private String group; + @CFNotNull + private Integer delayLevel; + + + @Override + public void checkFields() throws RemotingCommandException { + + } + + + public Long getOffset() { + return offset; + } + + + public void setOffset(Long offset) { + this.offset = offset; + } + + + public String getGroup() { + return group; + } + + + public void setGroup(String group) { + this.group = group; + } + + + public Integer getDelayLevel() { + return delayLevel; + } + + + public void setDelayLevel(Integer delayLevel) { + this.delayLevel = delayLevel; + } + + + @Override + public String toString() { + return "ConsumerSendMsgBackRequestHeader [offset=" + offset + ", group=" + group + ", delayLevel=" + + delayLevel + "]"; + } +} diff --git a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/CreateTopicRequestHeader.java b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/CreateTopicRequestHeader.java index 0dfe4aa7..a2d0f39b 100644 --- a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/CreateTopicRequestHeader.java +++ b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/CreateTopicRequestHeader.java @@ -10,8 +10,7 @@ /** - * @author vintage.wang@gmail.com shijia.wxr@taobao.com - * + * @author shijia.wxr */ public class CreateTopicRequestHeader implements CommandCustomHeader { @CFNotNull diff --git a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/DeleteSubscriptionGroupRequestHeader.java b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/DeleteSubscriptionGroupRequestHeader.java new file mode 100644 index 00000000..00b15cf6 --- /dev/null +++ b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/DeleteSubscriptionGroupRequestHeader.java @@ -0,0 +1,32 @@ +package com.alibaba.rocketmq.common.protocol.header; + +import com.alibaba.rocketmq.remoting.CommandCustomHeader; +import com.alibaba.rocketmq.remoting.annotation.CFNotNull; +import com.alibaba.rocketmq.remoting.exception.RemotingCommandException; + + +/** + * 删除订阅组请求参数 + * + * @author manhong.yqd + * @since 2013-8-22 + */ +public class DeleteSubscriptionGroupRequestHeader implements CommandCustomHeader { + @CFNotNull + private String groupName; + + + @Override + public void checkFields() throws RemotingCommandException { + } + + + public String getGroupName() { + return groupName; + } + + + public void setGroupName(String groupName) { + this.groupName = groupName; + } +} diff --git a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/DeleteTopicRequestHeader.java b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/DeleteTopicRequestHeader.java index 74408513..3d209845 100644 --- a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/DeleteTopicRequestHeader.java +++ b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/DeleteTopicRequestHeader.java @@ -9,8 +9,7 @@ /** - * @author vintage.wang@gmail.com shijia.wxr@taobao.com - * + * @author shijia.wxr */ public class DeleteTopicRequestHeader implements CommandCustomHeader { @CFNotNull diff --git a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/EndTransactionRequestHeader.java b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/EndTransactionRequestHeader.java index 77e5412e..4103f918 100644 --- a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/EndTransactionRequestHeader.java +++ b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/EndTransactionRequestHeader.java @@ -6,12 +6,12 @@ import com.alibaba.rocketmq.common.sysflag.MessageSysFlag; import com.alibaba.rocketmq.remoting.CommandCustomHeader; import com.alibaba.rocketmq.remoting.annotation.CFNotNull; +import com.alibaba.rocketmq.remoting.annotation.CFNullable; import com.alibaba.rocketmq.remoting.exception.RemotingCommandException; /** - * @author vintage.wang@gmail.com shijia.wxr@taobao.com - * + * @author shijia.wxr */ public class EndTransactionRequestHeader implements CommandCustomHeader { @CFNotNull @@ -22,11 +22,22 @@ public class EndTransactionRequestHeader implements CommandCustomHeader { private Long commitLogOffset; @CFNotNull private Integer commitOrRollback; // TransactionCommitType - // TransactionRollbackType + // TransactionRollbackType + // TransactionNotType + + @CFNullable + private Boolean fromTransactionCheck = false; + + @CFNotNull + private String msgId; @Override public void checkFields() throws RemotingCommandException { + if (MessageSysFlag.TransactionNotType == this.commitOrRollback) { + return; + } + if (MessageSysFlag.TransactionCommitType == this.commitOrRollback) { return; } @@ -77,4 +88,33 @@ public Integer getCommitOrRollback() { public void setCommitOrRollback(Integer commitOrRollback) { this.commitOrRollback = commitOrRollback; } + + + public Boolean getFromTransactionCheck() { + return fromTransactionCheck; + } + + + public void setFromTransactionCheck(Boolean fromTransactionCheck) { + this.fromTransactionCheck = fromTransactionCheck; + } + + + public String getMsgId() { + return msgId; + } + + + public void setMsgId(String msgId) { + this.msgId = msgId; + } + + + @Override + public String toString() { + return "EndTransactionRequestHeader [producerGroup=" + producerGroup + ", tranStateTableOffset=" + + tranStateTableOffset + ", commitLogOffset=" + commitLogOffset + ", commitOrRollback=" + + commitOrRollback + ", fromTransactionCheck=" + fromTransactionCheck + ", msgId=" + msgId + + "]"; + } } diff --git a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/EndTransactionResponseHeader.java b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/EndTransactionResponseHeader.java index 0a1520c4..3b0f772e 100644 --- a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/EndTransactionResponseHeader.java +++ b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/EndTransactionResponseHeader.java @@ -8,8 +8,7 @@ /** - * @author vintage.wang@gmail.com shijia.wxr@taobao.com - * + * @author shijia.wxr */ public class EndTransactionResponseHeader implements CommandCustomHeader { diff --git a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/GetAllTopicConfigResponseHeader.java b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/GetAllTopicConfigResponseHeader.java index 0d216a88..d9ba1a52 100644 --- a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/GetAllTopicConfigResponseHeader.java +++ b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/GetAllTopicConfigResponseHeader.java @@ -4,66 +4,15 @@ package com.alibaba.rocketmq.common.protocol.header; import com.alibaba.rocketmq.remoting.CommandCustomHeader; -import com.alibaba.rocketmq.remoting.annotation.CFNotNull; import com.alibaba.rocketmq.remoting.exception.RemotingCommandException; /** - * @author vintage.wang@gmail.com shijia.wxr@taobao.com - * + * @author shijia.wxr */ public class GetAllTopicConfigResponseHeader implements CommandCustomHeader { - @CFNotNull - private String version; - @CFNotNull - private String brokerName; - @CFNotNull - private Long brokerId; - @CFNotNull - private String clusterName; - @Override public void checkFields() throws RemotingCommandException { } - - - public String getVersion() { - return version; - } - - - public void setVersion(String version) { - this.version = version; - } - - - public String getBrokerName() { - return brokerName; - } - - - public void setBrokerName(String brokerName) { - this.brokerName = brokerName; - } - - - public String getClusterName() { - return clusterName; - } - - - public void setClusterName(String clusterName) { - this.clusterName = clusterName; - } - - - public Long getBrokerId() { - return brokerId; - } - - - public void setBrokerId(Long brokerId) { - this.brokerId = brokerId; - } } diff --git a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/GetBrokerConfigResponseHeader.java b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/GetBrokerConfigResponseHeader.java index 0aad5b7a..bb9f3327 100644 --- a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/GetBrokerConfigResponseHeader.java +++ b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/GetBrokerConfigResponseHeader.java @@ -9,8 +9,7 @@ /** - * @author vintage.wang@gmail.com shijia.wxr@taobao.com - * + * @author shijia.wxr */ public class GetBrokerConfigResponseHeader implements CommandCustomHeader { @CFNotNull diff --git a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/GetConsumeStatsRequestHeader.java b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/GetConsumeStatsRequestHeader.java new file mode 100644 index 00000000..1b6972f1 --- /dev/null +++ b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/GetConsumeStatsRequestHeader.java @@ -0,0 +1,47 @@ +/** + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.rocketmq.common.protocol.header; + +import com.alibaba.rocketmq.remoting.CommandCustomHeader; +import com.alibaba.rocketmq.remoting.annotation.CFNotNull; +import com.alibaba.rocketmq.remoting.exception.RemotingCommandException; + + +/** + * @author shijia.wxr + * @since 2013-8-11 + */ +public class GetConsumeStatsRequestHeader implements CommandCustomHeader { + @CFNotNull + private String consumerGroup; + + + @Override + public void checkFields() throws RemotingCommandException { + // TODO Auto-generated method stub + + } + + + public String getConsumerGroup() { + return consumerGroup; + } + + + public void setConsumerGroup(String consumerGroup) { + this.consumerGroup = consumerGroup; + } +} diff --git a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/GetConsumerConnectionListRequestHeader.java b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/GetConsumerConnectionListRequestHeader.java new file mode 100644 index 00000000..b0542ffc --- /dev/null +++ b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/GetConsumerConnectionListRequestHeader.java @@ -0,0 +1,34 @@ +package com.alibaba.rocketmq.common.protocol.header; + +import com.alibaba.rocketmq.remoting.CommandCustomHeader; +import com.alibaba.rocketmq.remoting.annotation.CFNotNull; +import com.alibaba.rocketmq.remoting.exception.RemotingCommandException; + + +/** + * TODO + * + * @author shijia.wxr + * @since 13-8-5 + */ +public class GetConsumerConnectionListRequestHeader implements CommandCustomHeader { + @CFNotNull + private String consumerGroup; + + + @Override + public void checkFields() throws RemotingCommandException { + // To change body of implemented methods use File | Settings | File + // Templates. + } + + + public String getConsumerGroup() { + return consumerGroup; + } + + + public void setConsumerGroup(String consumerGroup) { + this.consumerGroup = consumerGroup; + } +} diff --git a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/GetConsumerListByGroupRequestHeader.java b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/GetConsumerListByGroupRequestHeader.java new file mode 100644 index 00000000..7bdddd0e --- /dev/null +++ b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/GetConsumerListByGroupRequestHeader.java @@ -0,0 +1,29 @@ +package com.alibaba.rocketmq.common.protocol.header; + +import com.alibaba.rocketmq.remoting.CommandCustomHeader; +import com.alibaba.rocketmq.remoting.annotation.CFNotNull; +import com.alibaba.rocketmq.remoting.exception.RemotingCommandException; + + +/** + * @author shijia.wxr + */ +public class GetConsumerListByGroupRequestHeader implements CommandCustomHeader { + @CFNotNull + private String consumerGroup; + + + @Override + public void checkFields() throws RemotingCommandException { + } + + + public String getConsumerGroup() { + return consumerGroup; + } + + + public void setConsumerGroup(String consumerGroup) { + this.consumerGroup = consumerGroup; + } +} diff --git a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/GetConsumerListByGroupResponseBody.java b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/GetConsumerListByGroupResponseBody.java new file mode 100644 index 00000000..2e375118 --- /dev/null +++ b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/GetConsumerListByGroupResponseBody.java @@ -0,0 +1,23 @@ +package com.alibaba.rocketmq.common.protocol.header; + +import java.util.List; + +import com.alibaba.rocketmq.remoting.protocol.RemotingSerializable; + + +/** + * @author shijia.wxr + */ +public class GetConsumerListByGroupResponseBody extends RemotingSerializable { + private List consumerIdList; + + + public List getConsumerIdList() { + return consumerIdList; + } + + + public void setConsumerIdList(List consumerIdList) { + this.consumerIdList = consumerIdList; + } +} diff --git a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/GetConsumerListByGroupResponseHeader.java b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/GetConsumerListByGroupResponseHeader.java new file mode 100644 index 00000000..2e4b30cb --- /dev/null +++ b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/GetConsumerListByGroupResponseHeader.java @@ -0,0 +1,15 @@ +package com.alibaba.rocketmq.common.protocol.header; + +import com.alibaba.rocketmq.remoting.CommandCustomHeader; +import com.alibaba.rocketmq.remoting.exception.RemotingCommandException; + + +/** + * @author shijia.wxr + */ +public class GetConsumerListByGroupResponseHeader implements CommandCustomHeader { + + @Override + public void checkFields() throws RemotingCommandException { + } +} diff --git a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/GetConsumerStatusRequestHeader.java b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/GetConsumerStatusRequestHeader.java new file mode 100644 index 00000000..b80a6f7a --- /dev/null +++ b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/GetConsumerStatusRequestHeader.java @@ -0,0 +1,58 @@ +package com.alibaba.rocketmq.common.protocol.header; + +import com.alibaba.rocketmq.remoting.CommandCustomHeader; +import com.alibaba.rocketmq.remoting.annotation.CFNotNull; +import com.alibaba.rocketmq.remoting.annotation.CFNullable; +import com.alibaba.rocketmq.remoting.exception.RemotingCommandException; + + +/** + * 查看客户端消费组的消费情况。 + * + * @author: manhong.yqd + * @since: 13-12-30 + */ +public class GetConsumerStatusRequestHeader implements CommandCustomHeader { + @CFNotNull + private String topic; + @CFNotNull + private String group; + @CFNullable + private String clientAddr; + + + @Override + public void checkFields() throws RemotingCommandException { + // TODO Auto-generated method stub + } + + + public String getTopic() { + return topic; + } + + + public void setTopic(String topic) { + this.topic = topic; + } + + + public String getGroup() { + return group; + } + + + public void setGroup(String group) { + this.group = group; + } + + + public String getClientAddr() { + return clientAddr; + } + + + public void setClientAddr(String clientAddr) { + this.clientAddr = clientAddr; + } +} diff --git a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/GetEarliestMsgStoretimeRequestHeader.java b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/GetEarliestMsgStoretimeRequestHeader.java index c56f3b7a..98400465 100644 --- a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/GetEarliestMsgStoretimeRequestHeader.java +++ b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/GetEarliestMsgStoretimeRequestHeader.java @@ -9,8 +9,7 @@ /** - * @author vintage.wang@gmail.com shijia.wxr@taobao.com - * + * @author shijia.wxr */ public class GetEarliestMsgStoretimeRequestHeader implements CommandCustomHeader { @CFNotNull diff --git a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/GetEarliestMsgStoretimeResponseHeader.java b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/GetEarliestMsgStoretimeResponseHeader.java index 23f668a0..185349d5 100644 --- a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/GetEarliestMsgStoretimeResponseHeader.java +++ b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/GetEarliestMsgStoretimeResponseHeader.java @@ -9,8 +9,7 @@ /** - * @author vintage.wang@gmail.com shijia.wxr@taobao.com - * + * @author shijia.wxr */ public class GetEarliestMsgStoretimeResponseHeader implements CommandCustomHeader { @CFNotNull diff --git a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/GetMaxOffsetRequestHeader.java b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/GetMaxOffsetRequestHeader.java index 4620ff28..c96c7734 100644 --- a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/GetMaxOffsetRequestHeader.java +++ b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/GetMaxOffsetRequestHeader.java @@ -9,8 +9,7 @@ /** - * @author vintage.wang@gmail.com shijia.wxr@taobao.com - * + * @author shijia.wxr */ public class GetMaxOffsetRequestHeader implements CommandCustomHeader { @CFNotNull diff --git a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/GetMaxOffsetResponseHeader.java b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/GetMaxOffsetResponseHeader.java index b30c03d7..c5ec5499 100644 --- a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/GetMaxOffsetResponseHeader.java +++ b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/GetMaxOffsetResponseHeader.java @@ -9,8 +9,7 @@ /** - * @author vintage.wang@gmail.com shijia.wxr@taobao.com - * + * @author shijia.wxr */ public class GetMaxOffsetResponseHeader implements CommandCustomHeader { @CFNotNull diff --git a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/GetMinOffsetRequestHeader.java b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/GetMinOffsetRequestHeader.java index 0aac1a04..254a9bc4 100644 --- a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/GetMinOffsetRequestHeader.java +++ b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/GetMinOffsetRequestHeader.java @@ -9,8 +9,7 @@ /** - * @author vintage.wang@gmail.com shijia.wxr@taobao.com - * + * @author shijia.wxr */ public class GetMinOffsetRequestHeader implements CommandCustomHeader { @CFNotNull diff --git a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/GetMinOffsetResponseHeader.java b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/GetMinOffsetResponseHeader.java index cd10d6d5..e8ae3db8 100644 --- a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/GetMinOffsetResponseHeader.java +++ b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/GetMinOffsetResponseHeader.java @@ -9,8 +9,7 @@ /** - * @author vintage.wang@gmail.com shijia.wxr@taobao.com - * + * @author shijia.wxr */ public class GetMinOffsetResponseHeader implements CommandCustomHeader { @CFNotNull diff --git a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/GetProducerConnectionListRequestHeader.java b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/GetProducerConnectionListRequestHeader.java new file mode 100644 index 00000000..4a8e98a7 --- /dev/null +++ b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/GetProducerConnectionListRequestHeader.java @@ -0,0 +1,34 @@ +package com.alibaba.rocketmq.common.protocol.header; + +import com.alibaba.rocketmq.remoting.CommandCustomHeader; +import com.alibaba.rocketmq.remoting.annotation.CFNotNull; +import com.alibaba.rocketmq.remoting.exception.RemotingCommandException; + + +/** + * TODO + * + * @author shijia.wxr + * @since 13-8-5 + */ +public class GetProducerConnectionListRequestHeader implements CommandCustomHeader { + @CFNotNull + private String producerGroup; + + + @Override + public void checkFields() throws RemotingCommandException { + // To change body of implemented methods use File | Settings | File + // Templates. + } + + + public String getProducerGroup() { + return producerGroup; + } + + + public void setProducerGroup(String producerGroup) { + this.producerGroup = producerGroup; + } +} diff --git a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/GetTopicStatsInfoRequestHeader.java b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/GetTopicStatsInfoRequestHeader.java new file mode 100644 index 00000000..b470d682 --- /dev/null +++ b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/GetTopicStatsInfoRequestHeader.java @@ -0,0 +1,30 @@ +package com.alibaba.rocketmq.common.protocol.header; + +import com.alibaba.rocketmq.remoting.CommandCustomHeader; +import com.alibaba.rocketmq.remoting.annotation.CFNotNull; +import com.alibaba.rocketmq.remoting.exception.RemotingCommandException; + + +/** + * @author shijia.wxr + * @since 13-8-4 + */ +public class GetTopicStatsInfoRequestHeader implements CommandCustomHeader { + @CFNotNull + private String topic; + + + @Override + public void checkFields() throws RemotingCommandException { + } + + + public String getTopic() { + return topic; + } + + + public void setTopic(String topic) { + this.topic = topic; + } +} diff --git a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/NotifyConsumerIdsChangedRequestHeader.java b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/NotifyConsumerIdsChangedRequestHeader.java new file mode 100644 index 00000000..89e561b9 --- /dev/null +++ b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/NotifyConsumerIdsChangedRequestHeader.java @@ -0,0 +1,30 @@ +package com.alibaba.rocketmq.common.protocol.header; + +import com.alibaba.rocketmq.remoting.CommandCustomHeader; +import com.alibaba.rocketmq.remoting.annotation.CFNotNull; +import com.alibaba.rocketmq.remoting.exception.RemotingCommandException; + + +/** + * @author shijia.wxr + */ +public class NotifyConsumerIdsChangedRequestHeader implements CommandCustomHeader { + @CFNotNull + private String consumerGroup; + + + @Override + public void checkFields() throws RemotingCommandException { + // TODO Auto-generated method stub + } + + + public String getConsumerGroup() { + return consumerGroup; + } + + + public void setConsumerGroup(String consumerGroup) { + this.consumerGroup = consumerGroup; + } +} diff --git a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/PullMessageRequestHeader.java b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/PullMessageRequestHeader.java index 0e5566ff..c60f2eb1 100644 --- a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/PullMessageRequestHeader.java +++ b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/PullMessageRequestHeader.java @@ -5,12 +5,12 @@ import com.alibaba.rocketmq.remoting.CommandCustomHeader; import com.alibaba.rocketmq.remoting.annotation.CFNotNull; +import com.alibaba.rocketmq.remoting.annotation.CFNullable; import com.alibaba.rocketmq.remoting.exception.RemotingCommandException; /** - * @author vintage.wang@gmail.com shijia.wxr@taobao.com - * + * @author shijia.wxr */ public class PullMessageRequestHeader implements CommandCustomHeader { @CFNotNull @@ -29,8 +29,10 @@ public class PullMessageRequestHeader implements CommandCustomHeader { private Long commitOffset; @CFNotNull private Long suspendTimeoutMillis; - @CFNotNull + @CFNullable private String subscription; + @CFNotNull + private Long subVersion; @Override @@ -126,4 +128,14 @@ public String getSubscription() { public void setSubscription(String subscription) { this.subscription = subscription; } + + + public Long getSubVersion() { + return subVersion; + } + + + public void setSubVersion(Long subVersion) { + this.subVersion = subVersion; + } } diff --git a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/PullMessageResponseHeader.java b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/PullMessageResponseHeader.java index a0298597..dee1f13e 100644 --- a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/PullMessageResponseHeader.java +++ b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/PullMessageResponseHeader.java @@ -9,12 +9,11 @@ /** - * @author vintage.wang@gmail.com shijia.wxr@taobao.com - * + * @author shijia.wxr */ public class PullMessageResponseHeader implements CommandCustomHeader { @CFNotNull - private Boolean suggestPullingFromSlave; + private Long suggestWhichBrokerId; @CFNotNull private Long nextBeginOffset; @CFNotNull @@ -28,16 +27,6 @@ public void checkFields() throws RemotingCommandException { } - public Boolean getSuggestPullingFromSlave() { - return suggestPullingFromSlave; - } - - - public void setSuggestPullingFromSlave(Boolean suggestPullingFromSlave) { - this.suggestPullingFromSlave = suggestPullingFromSlave; - } - - public Long getNextBeginOffset() { return nextBeginOffset; } @@ -66,4 +55,14 @@ public Long getMaxOffset() { public void setMaxOffset(Long maxOffset) { this.maxOffset = maxOffset; } + + + public Long getSuggestWhichBrokerId() { + return suggestWhichBrokerId; + } + + + public void setSuggestWhichBrokerId(Long suggestWhichBrokerId) { + this.suggestWhichBrokerId = suggestWhichBrokerId; + } } diff --git a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/QueryConsumerOffsetRequestHeader.java b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/QueryConsumerOffsetRequestHeader.java index d1b361e2..761bafc9 100644 --- a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/QueryConsumerOffsetRequestHeader.java +++ b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/QueryConsumerOffsetRequestHeader.java @@ -9,8 +9,7 @@ /** - * @author vintage.wang@gmail.com shijia.wxr@taobao.com - * + * @author shijia.wxr */ public class QueryConsumerOffsetRequestHeader implements CommandCustomHeader { @CFNotNull diff --git a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/QueryConsumerOffsetResponseHeader.java b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/QueryConsumerOffsetResponseHeader.java index 5e106493..c0b768e4 100644 --- a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/QueryConsumerOffsetResponseHeader.java +++ b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/QueryConsumerOffsetResponseHeader.java @@ -9,8 +9,7 @@ /** - * @author vintage.wang@gmail.com shijia.wxr@taobao.com - * + * @author shijia.wxr */ public class QueryConsumerOffsetResponseHeader implements CommandCustomHeader { @CFNotNull diff --git a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/QueryMessageRequestHeader.java b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/QueryMessageRequestHeader.java index fdff8929..957da6d3 100644 --- a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/QueryMessageRequestHeader.java +++ b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/QueryMessageRequestHeader.java @@ -9,8 +9,7 @@ /** - * @author vintage.wang@gmail.com shijia.wxr@taobao.com - * + * @author shijia.wxr */ public class QueryMessageRequestHeader implements CommandCustomHeader { @CFNotNull diff --git a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/QueryMessageResponseHeader.java b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/QueryMessageResponseHeader.java index bc99ac0e..6cb334e5 100644 --- a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/QueryMessageResponseHeader.java +++ b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/QueryMessageResponseHeader.java @@ -9,8 +9,7 @@ /** - * @author vintage.wang@gmail.com shijia.wxr@taobao.com - * + * @author shijia.wxr */ public class QueryMessageResponseHeader implements CommandCustomHeader { @CFNotNull diff --git a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/ResetOffsetRequestHeader.java b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/ResetOffsetRequestHeader.java new file mode 100644 index 00000000..1ff1c399 --- /dev/null +++ b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/ResetOffsetRequestHeader.java @@ -0,0 +1,69 @@ +package com.alibaba.rocketmq.common.protocol.header; + +import com.alibaba.rocketmq.remoting.CommandCustomHeader; +import com.alibaba.rocketmq.remoting.annotation.CFNotNull; +import com.alibaba.rocketmq.remoting.exception.RemotingCommandException; + + +/** + * 重置 offset。 + * + * @author: manhong.yqd + * @since: 13-12-30 + */ +public class ResetOffsetRequestHeader implements CommandCustomHeader { + @CFNotNull + private String topic; + @CFNotNull + private String group; + @CFNotNull + private long timestamp; + @CFNotNull + private boolean isForce; + + + public String getTopic() { + return topic; + } + + + public void setTopic(String topic) { + this.topic = topic; + } + + + public String getGroup() { + return group; + } + + + public void setGroup(String group) { + this.group = group; + } + + + public long getTimestamp() { + return timestamp; + } + + + public void setTimestamp(long timestamp) { + this.timestamp = timestamp; + } + + + public boolean isForce() { + return isForce; + } + + + public void setForce(boolean isForce) { + this.isForce = isForce; + } + + + @Override + public void checkFields() throws RemotingCommandException { + + } +} diff --git a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/SearchOffsetRequestHeader.java b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/SearchOffsetRequestHeader.java index 6c47890b..1e5e7c7e 100644 --- a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/SearchOffsetRequestHeader.java +++ b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/SearchOffsetRequestHeader.java @@ -9,8 +9,7 @@ /** - * @author vintage.wang@gmail.com shijia.wxr@taobao.com - * + * @author shijia.wxr */ public class SearchOffsetRequestHeader implements CommandCustomHeader { @CFNotNull diff --git a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/SearchOffsetResponseHeader.java b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/SearchOffsetResponseHeader.java index f2566d86..9d812ee1 100644 --- a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/SearchOffsetResponseHeader.java +++ b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/SearchOffsetResponseHeader.java @@ -9,8 +9,7 @@ /** - * @author vintage.wang@gmail.com shijia.wxr@taobao.com - * + * @author shijia.wxr */ public class SearchOffsetResponseHeader implements CommandCustomHeader { @CFNotNull diff --git a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/SendMessageRequestHeader.java b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/SendMessageRequestHeader.java index 2e1b961a..f8f2f8e8 100644 --- a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/SendMessageRequestHeader.java +++ b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/SendMessageRequestHeader.java @@ -10,8 +10,7 @@ /** - * @author vintage.wang@gmail.com shijia.wxr@taobao.com - * + * @author shijia.wxr */ public class SendMessageRequestHeader implements CommandCustomHeader { @CFNotNull diff --git a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/SendMessageResponseHeader.java b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/SendMessageResponseHeader.java index 15151445..a800e955 100644 --- a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/SendMessageResponseHeader.java +++ b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/SendMessageResponseHeader.java @@ -9,8 +9,7 @@ /** - * @author vintage.wang@gmail.com shijia.wxr@taobao.com - * + * @author shijia.wxr */ public class SendMessageResponseHeader implements CommandCustomHeader { @CFNotNull diff --git a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/UnregisterClientRequestHeader.java b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/UnregisterClientRequestHeader.java index 124a3a86..d6e47268 100644 --- a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/UnregisterClientRequestHeader.java +++ b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/UnregisterClientRequestHeader.java @@ -1,5 +1,5 @@ /** - * + * */ package com.alibaba.rocketmq.common.protocol.header; @@ -10,7 +10,7 @@ /** - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * @author shijia.wxr */ public class UnregisterClientRequestHeader implements CommandCustomHeader { @CFNotNull diff --git a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/UnregisterClientResponseHeader.java b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/UnregisterClientResponseHeader.java index 0836b7f2..fb25f0a8 100644 --- a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/UnregisterClientResponseHeader.java +++ b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/UnregisterClientResponseHeader.java @@ -1,17 +1,20 @@ /** - * + * */ package com.alibaba.rocketmq.common.protocol.header; import com.alibaba.rocketmq.remoting.CommandCustomHeader; import com.alibaba.rocketmq.remoting.exception.RemotingCommandException; + /** - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * @author shijia.wxr */ public class UnregisterClientResponseHeader implements CommandCustomHeader { - /* (non-Javadoc) + /* + * (non-Javadoc) + * * @see com.alibaba.rocketmq.remoting.CommandCustomHeader#checkFields() */ @Override diff --git a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/UpdateConsumerOffsetRequestHeader.java b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/UpdateConsumerOffsetRequestHeader.java index 1f7768e5..7e114f7c 100644 --- a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/UpdateConsumerOffsetRequestHeader.java +++ b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/UpdateConsumerOffsetRequestHeader.java @@ -9,8 +9,7 @@ /** - * @author vintage.wang@gmail.com shijia.wxr@taobao.com - * + * @author shijia.wxr */ public class UpdateConsumerOffsetRequestHeader implements CommandCustomHeader { @CFNotNull diff --git a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/UpdateConsumerOffsetResponseHeader.java b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/UpdateConsumerOffsetResponseHeader.java index 6be10e8e..e8791a69 100644 --- a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/UpdateConsumerOffsetResponseHeader.java +++ b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/UpdateConsumerOffsetResponseHeader.java @@ -8,8 +8,7 @@ /** - * @author vintage.wang@gmail.com shijia.wxr@taobao.com - * + * @author shijia.wxr */ public class UpdateConsumerOffsetResponseHeader implements CommandCustomHeader { @Override diff --git a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/ViewMessageRequestHeader.java b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/ViewMessageRequestHeader.java index c3e97f1b..a01d5956 100644 --- a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/ViewMessageRequestHeader.java +++ b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/ViewMessageRequestHeader.java @@ -9,8 +9,7 @@ /** - * @author vintage.wang@gmail.com shijia.wxr@taobao.com - * + * @author shijia.wxr */ public class ViewMessageRequestHeader implements CommandCustomHeader { @CFNotNull diff --git a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/ViewMessageResponseHeader.java b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/ViewMessageResponseHeader.java index 73437e86..b48f650b 100644 --- a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/ViewMessageResponseHeader.java +++ b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/ViewMessageResponseHeader.java @@ -8,8 +8,7 @@ /** - * @author vintage.wang@gmail.com shijia.wxr@taobao.com - * + * @author shijia.wxr */ public class ViewMessageResponseHeader implements CommandCustomHeader { diff --git a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/namesrv/DeleteKVConfigRequestHeader.java b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/namesrv/DeleteKVConfigRequestHeader.java new file mode 100644 index 00000000..d602ae9a --- /dev/null +++ b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/namesrv/DeleteKVConfigRequestHeader.java @@ -0,0 +1,42 @@ +package com.alibaba.rocketmq.common.protocol.header.namesrv; + +import com.alibaba.rocketmq.remoting.CommandCustomHeader; +import com.alibaba.rocketmq.remoting.annotation.CFNotNull; +import com.alibaba.rocketmq.remoting.exception.RemotingCommandException; + + +/** + * @author shijia.wxr + * @since 2013-7-1 + */ +public class DeleteKVConfigRequestHeader implements CommandCustomHeader { + @CFNotNull + private String namespace; + @CFNotNull + private String key; + + + @Override + public void checkFields() throws RemotingCommandException { + } + + + public String getNamespace() { + return namespace; + } + + + public void setNamespace(String namespace) { + this.namespace = namespace; + } + + + public String getKey() { + return key; + } + + + public void setKey(String key) { + this.key = key; + } +} diff --git a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/namesrv/DeleteTopicInNamesrvRequestHeader.java b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/namesrv/DeleteTopicInNamesrvRequestHeader.java new file mode 100644 index 00000000..0bd324a9 --- /dev/null +++ b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/namesrv/DeleteTopicInNamesrvRequestHeader.java @@ -0,0 +1,45 @@ +/** + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.rocketmq.common.protocol.header.namesrv; + +import com.alibaba.rocketmq.remoting.CommandCustomHeader; +import com.alibaba.rocketmq.remoting.annotation.CFNotNull; +import com.alibaba.rocketmq.remoting.exception.RemotingCommandException; + + +/** + * @author shijia.wxr + * @since 2013-8-11 + */ +public class DeleteTopicInNamesrvRequestHeader implements CommandCustomHeader { + @CFNotNull + private String topic; + + + @Override + public void checkFields() throws RemotingCommandException { + } + + + public String getTopic() { + return topic; + } + + + public void setTopic(String topic) { + this.topic = topic; + } +} diff --git a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/namesrv/GetKVConfigRequestHeader.java b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/namesrv/GetKVConfigRequestHeader.java new file mode 100644 index 00000000..93782fc4 --- /dev/null +++ b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/namesrv/GetKVConfigRequestHeader.java @@ -0,0 +1,42 @@ +package com.alibaba.rocketmq.common.protocol.header.namesrv; + +import com.alibaba.rocketmq.remoting.CommandCustomHeader; +import com.alibaba.rocketmq.remoting.annotation.CFNotNull; +import com.alibaba.rocketmq.remoting.exception.RemotingCommandException; + + +/** + * @author shijia.wxr + * @since 2013-7-1 + */ +public class GetKVConfigRequestHeader implements CommandCustomHeader { + @CFNotNull + private String namespace; + @CFNotNull + private String key; + + + @Override + public void checkFields() throws RemotingCommandException { + } + + + public String getNamespace() { + return namespace; + } + + + public void setNamespace(String namespace) { + this.namespace = namespace; + } + + + public String getKey() { + return key; + } + + + public void setKey(String key) { + this.key = key; + } +} diff --git a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/namesrv/GetKVConfigResponseHeader.java b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/namesrv/GetKVConfigResponseHeader.java new file mode 100644 index 00000000..91d00e8f --- /dev/null +++ b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/namesrv/GetKVConfigResponseHeader.java @@ -0,0 +1,30 @@ +package com.alibaba.rocketmq.common.protocol.header.namesrv; + +import com.alibaba.rocketmq.remoting.CommandCustomHeader; +import com.alibaba.rocketmq.remoting.annotation.CFNullable; +import com.alibaba.rocketmq.remoting.exception.RemotingCommandException; + + +/** + * @author shijia.wxr + * @since 2013-7-1 + */ +public class GetKVConfigResponseHeader implements CommandCustomHeader { + @CFNullable + private String value; + + + @Override + public void checkFields() throws RemotingCommandException { + } + + + public String getValue() { + return value; + } + + + public void setValue(String value) { + this.value = value; + } +} diff --git a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/namesrv/GetKVListByNamespaceRequestHeader.java b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/namesrv/GetKVListByNamespaceRequestHeader.java new file mode 100644 index 00000000..f1fa6b57 --- /dev/null +++ b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/namesrv/GetKVListByNamespaceRequestHeader.java @@ -0,0 +1,30 @@ +package com.alibaba.rocketmq.common.protocol.header.namesrv; + +import com.alibaba.rocketmq.remoting.CommandCustomHeader; +import com.alibaba.rocketmq.remoting.annotation.CFNotNull; +import com.alibaba.rocketmq.remoting.exception.RemotingCommandException; + + +/** + * @author shijia.wxr + * @since 2013-7-1 + */ +public class GetKVListByNamespaceRequestHeader implements CommandCustomHeader { + @CFNotNull + private String namespace; + + + @Override + public void checkFields() throws RemotingCommandException { + } + + + public String getNamespace() { + return namespace; + } + + + public void setNamespace(String namespace) { + this.namespace = namespace; + } +} diff --git a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/namesrv/GetRouteInfoRequestHeader.java b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/namesrv/GetRouteInfoRequestHeader.java index 90d6828f..b8ba6c93 100644 --- a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/namesrv/GetRouteInfoRequestHeader.java +++ b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/namesrv/GetRouteInfoRequestHeader.java @@ -9,8 +9,7 @@ /** - * @author vintage.wang@gmail.com shijia.wxr@taobao.com - * + * @author shijia.wxr */ public class GetRouteInfoRequestHeader implements CommandCustomHeader { @CFNotNull diff --git a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/namesrv/GetRouteInfoResponseHeader.java b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/namesrv/GetRouteInfoResponseHeader.java index f76605a8..06f46aa3 100644 --- a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/namesrv/GetRouteInfoResponseHeader.java +++ b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/namesrv/GetRouteInfoResponseHeader.java @@ -8,8 +8,7 @@ /** - * @author vintage.wang@gmail.com shijia.wxr@taobao.com - * + * @author shijia.wxr */ public class GetRouteInfoResponseHeader implements CommandCustomHeader { diff --git a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/namesrv/GetTopicResponseHeader.java b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/namesrv/GetTopicResponseHeader.java deleted file mode 100644 index 5d253348..00000000 --- a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/namesrv/GetTopicResponseHeader.java +++ /dev/null @@ -1,70 +0,0 @@ -/** - * $Id: GetTopicResponseHeader.java 1835 2013-05-16 02:00:50Z shijia.wxr $ - */ -package com.alibaba.rocketmq.common.protocol.header.namesrv; - -import com.alibaba.rocketmq.remoting.CommandCustomHeader; -import com.alibaba.rocketmq.remoting.annotation.CFNotNull; -import com.alibaba.rocketmq.remoting.exception.RemotingCommandException; - - -/** - * @author lansheng.zj@taobao.com - */ -public class GetTopicResponseHeader implements CommandCustomHeader { - - private String version; - @CFNotNull - private String brokerName; - @CFNotNull - private long brokerId; - private String cluster; - - - public String getCluster() { - return cluster; - } - - - public void setCluster(String cluster) { - this.cluster = cluster; - } - - - public String getVersion() { - return version; - } - - - public void setVersion(String version) { - this.version = version; - } - - - public String getBrokerName() { - return brokerName; - } - - - public void setBrokerName(String brokerName) { - this.brokerName = brokerName; - } - - - public long getBrokerId() { - return brokerId; - } - - - public void setBrokerId(long brokerId) { - this.brokerId = brokerId; - } - - - @Override - public void checkFields() throws RemotingCommandException { - // TODO Auto-generated method stub - - } - -} diff --git a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/namesrv/PutKVConfigRequestHeader.java b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/namesrv/PutKVConfigRequestHeader.java new file mode 100644 index 00000000..9f7edbb4 --- /dev/null +++ b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/namesrv/PutKVConfigRequestHeader.java @@ -0,0 +1,50 @@ +package com.alibaba.rocketmq.common.protocol.header.namesrv; + +import com.alibaba.rocketmq.remoting.CommandCustomHeader; +import com.alibaba.rocketmq.remoting.annotation.CFNotNull; +import com.alibaba.rocketmq.remoting.exception.RemotingCommandException; + + +public class PutKVConfigRequestHeader implements CommandCustomHeader { + @CFNotNull + private String namespace; + @CFNotNull + private String key; + @CFNotNull + private String value; + + + @Override + public void checkFields() throws RemotingCommandException { + } + + + public String getNamespace() { + return namespace; + } + + + public void setNamespace(String namespace) { + this.namespace = namespace; + } + + + public String getKey() { + return key; + } + + + public void setKey(String key) { + this.key = key; + } + + + public String getValue() { + return value; + } + + + public void setValue(String value) { + this.value = value; + } +} diff --git a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/namesrv/RegisterBrokerRequestHeader.java b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/namesrv/RegisterBrokerRequestHeader.java index cd12b5c6..ee2dfdcb 100644 --- a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/namesrv/RegisterBrokerRequestHeader.java +++ b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/namesrv/RegisterBrokerRequestHeader.java @@ -12,8 +12,31 @@ * @author lansheng.zj@taobao.com */ public class RegisterBrokerRequestHeader implements CommandCustomHeader { + @CFNotNull + private String brokerName; @CFNotNull private String brokerAddr; + @CFNotNull + private String clusterName; + @CFNotNull + private String haServerAddr; + @CFNotNull + private Long brokerId; + + + @Override + public void checkFields() throws RemotingCommandException { + } + + + public String getBrokerName() { + return brokerName; + } + + + public void setBrokerName(String brokerName) { + this.brokerName = brokerName; + } public String getBrokerAddr() { @@ -26,10 +49,32 @@ public void setBrokerAddr(String brokerAddr) { } - @Override - public void checkFields() throws RemotingCommandException { - // TODO Auto-generated method stub + public String getClusterName() { + return clusterName; + } + + public void setClusterName(String clusterName) { + this.clusterName = clusterName; } + + public String getHaServerAddr() { + return haServerAddr; + } + + + public void setHaServerAddr(String haServerAddr) { + this.haServerAddr = haServerAddr; + } + + + public Long getBrokerId() { + return brokerId; + } + + + public void setBrokerId(Long brokerId) { + this.brokerId = brokerId; + } } diff --git a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/namesrv/RegisterBrokerResponseHeader.java b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/namesrv/RegisterBrokerResponseHeader.java new file mode 100644 index 00000000..d7199ff4 --- /dev/null +++ b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/namesrv/RegisterBrokerResponseHeader.java @@ -0,0 +1,42 @@ +package com.alibaba.rocketmq.common.protocol.header.namesrv; + +import com.alibaba.rocketmq.remoting.CommandCustomHeader; +import com.alibaba.rocketmq.remoting.annotation.CFNullable; +import com.alibaba.rocketmq.remoting.exception.RemotingCommandException; + + +/** + * @author shijia.wxr + * @since 2013-7-4 + */ +public class RegisterBrokerResponseHeader implements CommandCustomHeader { + @CFNullable + private String haServerAddr; + @CFNullable + private String masterAddr; + + + @Override + public void checkFields() throws RemotingCommandException { + } + + + public String getHaServerAddr() { + return haServerAddr; + } + + + public void setHaServerAddr(String haServerAddr) { + this.haServerAddr = haServerAddr; + } + + + public String getMasterAddr() { + return masterAddr; + } + + + public void setMasterAddr(String masterAddr) { + this.masterAddr = masterAddr; + } +} diff --git a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/namesrv/RegisterOrderTopicRequestHeader.java b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/namesrv/RegisterOrderTopicRequestHeader.java index 8d23d6a1..b86aac70 100644 --- a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/namesrv/RegisterOrderTopicRequestHeader.java +++ b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/namesrv/RegisterOrderTopicRequestHeader.java @@ -9,8 +9,7 @@ /** - * @author vintage.wang@gmail.com shijia.wxr@taobao.com - * + * @author shijia.wxr */ public class RegisterOrderTopicRequestHeader implements CommandCustomHeader { @CFNotNull diff --git a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/namesrv/UnRegisterBrokerRequestHeader.java b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/namesrv/UnRegisterBrokerRequestHeader.java index dbef5028..f6fb2e37 100644 --- a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/namesrv/UnRegisterBrokerRequestHeader.java +++ b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/namesrv/UnRegisterBrokerRequestHeader.java @@ -12,9 +12,19 @@ * @author lansheng.zj@taobao.com */ public class UnRegisterBrokerRequestHeader implements CommandCustomHeader { - @CFNotNull private String brokerName; + @CFNotNull + private String brokerAddr; + @CFNotNull + private String clusterName; + @CFNotNull + private Long brokerId; + + + @Override + public void checkFields() throws RemotingCommandException { + } public String getBrokerName() { @@ -27,10 +37,32 @@ public void setBrokerName(String brokerName) { } - @Override - public void checkFields() throws RemotingCommandException { - // TODO Auto-generated method stub + public String getBrokerAddr() { + return brokerAddr; + } + + public void setBrokerAddr(String brokerAddr) { + this.brokerAddr = brokerAddr; + } + + + public String getClusterName() { + return clusterName; + } + + + public void setClusterName(String clusterName) { + this.clusterName = clusterName; + } + + + public Long getBrokerId() { + return brokerId; } + + public void setBrokerId(Long brokerId) { + this.brokerId = brokerId; + } } diff --git a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/namesrv/WipeWritePermOfBrokerRequestHeader.java b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/namesrv/WipeWritePermOfBrokerRequestHeader.java new file mode 100644 index 00000000..25f853fc --- /dev/null +++ b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/namesrv/WipeWritePermOfBrokerRequestHeader.java @@ -0,0 +1,47 @@ +/** + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.rocketmq.common.protocol.header.namesrv; + +import com.alibaba.rocketmq.remoting.CommandCustomHeader; +import com.alibaba.rocketmq.remoting.annotation.CFNotNull; +import com.alibaba.rocketmq.remoting.exception.RemotingCommandException; + + +/** + * @author shijia.wxr + * @since 2013-8-5 + */ +public class WipeWritePermOfBrokerRequestHeader implements CommandCustomHeader { + @CFNotNull + private String brokerName; + + + @Override + public void checkFields() throws RemotingCommandException { + // TODO Auto-generated method stub + + } + + + public String getBrokerName() { + return brokerName; + } + + + public void setBrokerName(String brokerName) { + this.brokerName = brokerName; + } +} diff --git a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/namesrv/WipeWritePermOfBrokerResponseHeader.java b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/namesrv/WipeWritePermOfBrokerResponseHeader.java new file mode 100644 index 00000000..7cfe2cff --- /dev/null +++ b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/header/namesrv/WipeWritePermOfBrokerResponseHeader.java @@ -0,0 +1,45 @@ +/** + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.rocketmq.common.protocol.header.namesrv; + +import com.alibaba.rocketmq.remoting.CommandCustomHeader; +import com.alibaba.rocketmq.remoting.annotation.CFNotNull; +import com.alibaba.rocketmq.remoting.exception.RemotingCommandException; + + +/** + * @author shijia.wxr + * @since 2013-8-5 + */ +public class WipeWritePermOfBrokerResponseHeader implements CommandCustomHeader { + @CFNotNull + private Integer wipeTopicCount; + + + @Override + public void checkFields() throws RemotingCommandException { + } + + + public Integer getWipeTopicCount() { + return wipeTopicCount; + } + + + public void setWipeTopicCount(Integer wipeTopicCount) { + this.wipeTopicCount = wipeTopicCount; + } +} diff --git a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/heartbeat/ConsumeType.java b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/heartbeat/ConsumeType.java index ead0768c..bd226c6f 100644 --- a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/heartbeat/ConsumeType.java +++ b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/heartbeat/ConsumeType.java @@ -4,18 +4,17 @@ package com.alibaba.rocketmq.common.protocol.heartbeat; /** - * - * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * 消费类型 * + * @author shijia.wxr */ public enum ConsumeType { /** - * ʽ + * 主动方式消费 */ CONSUME_ACTIVELY, /** - * ʽ + * 被动方式消费 */ CONSUME_PASSIVELY, } diff --git a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/heartbeat/ConsumerData.java b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/heartbeat/ConsumerData.java index 395a79a3..ad4742a7 100644 --- a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/heartbeat/ConsumerData.java +++ b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/heartbeat/ConsumerData.java @@ -6,53 +6,20 @@ import java.util.HashSet; import java.util.Set; -import com.alibaba.rocketmq.common.protocol.MQProtos.ConsumerInfo; -import com.alibaba.rocketmq.common.protocol.MQProtos.ProducerInfo; -import com.alibaba.rocketmq.common.protocol.MQProtos.SubscriptionInfo; +import com.alibaba.rocketmq.common.consumer.ConsumeFromWhere; /** - * @author vintage.wang@gmail.com shijia.wxr@taobao.com - * + * @author shijia.wxr */ public class ConsumerData { private String groupName; private ConsumeType consumeType; private MessageModel messageModel; + private ConsumeFromWhere consumeFromWhere; private Set subscriptionDataSet = new HashSet(); - public ConsumerInfo encode() { - ConsumerInfo.Builder builder = ConsumerInfo.newBuilder(); - builder.setGroupName(this.groupName); - builder.setConsumeType(this.consumeType.name()); - builder.setMessageModel(this.messageModel.name()); - if (subscriptionDataSet != null) { - int i = 0; - for (SubscriptionData data : this.subscriptionDataSet) { - builder.addSubscriptionInfos(i++, data.encode()); - } - } - - return builder.build(); - } - - - public static ConsumerData decode(ConsumerInfo info) { - ConsumerData data = new ConsumerData(); - data.setGroupName(info.getGroupName()); - data.setConsumeType(ConsumeType.valueOf(info.getConsumeType())); - data.setMessageModel(MessageModel.valueOf(info.getMessageModel())); - - // subscriptionDataSet - for (SubscriptionInfo sub : info.getSubscriptionInfosList()) { - data.getSubscriptionDataSet().add(SubscriptionData.decode(sub)); - } - - return data; - } - - public String getGroupName() { return groupName; } @@ -83,6 +50,16 @@ public void setMessageModel(MessageModel messageModel) { } + public ConsumeFromWhere getConsumeFromWhere() { + return consumeFromWhere; + } + + + public void setConsumeFromWhere(ConsumeFromWhere consumeFromWhere) { + this.consumeFromWhere = consumeFromWhere; + } + + public Set getSubscriptionDataSet() { return subscriptionDataSet; } @@ -96,6 +73,7 @@ public void setSubscriptionDataSet(Set subscriptionDataSet) { @Override public String toString() { return "ConsumerData [groupName=" + groupName + ", consumeType=" + consumeType + ", messageModel=" - + messageModel + ", subscriptionDataSet=" + subscriptionDataSet + "]"; + + messageModel + ", consumeFromWhere=" + consumeFromWhere + ", subscriptionDataSet=" + + subscriptionDataSet + "]"; } } diff --git a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/heartbeat/HeartbeatData.java b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/heartbeat/HeartbeatData.java index 02725b3d..df496e6f 100644 --- a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/heartbeat/HeartbeatData.java +++ b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/heartbeat/HeartbeatData.java @@ -6,77 +6,18 @@ import java.util.HashSet; import java.util.Set; -import com.alibaba.rocketmq.common.protocol.MQProtos.ConsumerInfo; -import com.alibaba.rocketmq.common.protocol.MQProtos.HeartbeatInfo; -import com.alibaba.rocketmq.common.protocol.MQProtos.ProducerInfo; -import com.google.protobuf.InvalidProtocolBufferException; +import com.alibaba.rocketmq.remoting.protocol.RemotingSerializable; /** - * @author vintage.wang@gmail.com shijia.wxr@taobao.com - * + * @author shijia.wxr */ -public class HeartbeatData { +public class HeartbeatData extends RemotingSerializable { private String clientID; private Set producerDataSet = new HashSet(); private Set consumerDataSet = new HashSet(); - public byte[] encode() { - HeartbeatInfo.Builder builder = HeartbeatInfo.newBuilder(); - - // clientID - builder.setClientID(this.clientID); - - // producerDataSet - if (this.producerDataSet != null) { - int i = 0; - for (ProducerData data : this.producerDataSet) { - builder.addProducerInfos(i++, data.encode()); - } - } - - // consumerDataSet - if (this.consumerDataSet != null) { - int i = 0; - for (ConsumerData data : this.consumerDataSet) { - builder.addConsumerInfos(i++, data.encode()); - } - } - - return builder.build().toByteArray(); - } - - - public static HeartbeatData decode(byte[] data) throws InvalidProtocolBufferException { - if (data != null) { - HeartbeatData heartbeatData = new HeartbeatData(); - HeartbeatInfo pbClientHeartbeat = HeartbeatInfo.parseFrom(data); - - // clientID - heartbeatData.setClientID(pbClientHeartbeat.getClientID()); - - // producerDataSet - { - for (ProducerInfo info : pbClientHeartbeat.getProducerInfosList()) { - heartbeatData.getProducerDataSet().add(ProducerData.decode(info)); - } - } - - // ConsumerData - { - for (ConsumerInfo info : pbClientHeartbeat.getConsumerInfosList()) { - heartbeatData.getConsumerDataSet().add(ConsumerData.decode(info)); - } - } - - return heartbeatData; - } - - return null; - } - - public String getClientID() { return clientID; } diff --git a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/heartbeat/MessageModel.java b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/heartbeat/MessageModel.java index 631353dd..473e2a96 100644 --- a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/heartbeat/MessageModel.java +++ b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/heartbeat/MessageModel.java @@ -4,22 +4,21 @@ package com.alibaba.rocketmq.common.protocol.heartbeat; /** - * Ϣģ - * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * 消息模型 * + * @author shijia.wxr */ public enum MessageModel { /** - * 㲥ģ + * 广播模型 */ BROADCASTING, /** - * Ⱥģ + * 集群模型 */ CLUSTERING, - /** - * δ֪ѣȷӦõϢģ - */ - UNKNOWNS, + // /** + // * 未知,如果是主动消费,很难确定应用的消息模型 + // */ + // UNKNOWNS, } diff --git a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/heartbeat/ProducerData.java b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/heartbeat/ProducerData.java index ef8f95e5..d20ee2ce 100644 --- a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/heartbeat/ProducerData.java +++ b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/heartbeat/ProducerData.java @@ -3,31 +3,13 @@ */ package com.alibaba.rocketmq.common.protocol.heartbeat; -import com.alibaba.rocketmq.common.protocol.MQProtos.ProducerInfo; - - /** - * @author vintage.wang@gmail.com shijia.wxr@taobao.com - * + * @author shijia.wxr */ public class ProducerData { private String groupName; - public ProducerInfo encode() { - ProducerInfo.Builder builder = ProducerInfo.newBuilder(); - builder.setGroupName(this.groupName); - return builder.build(); - } - - - public static ProducerData decode(ProducerInfo info) { - ProducerData data = new ProducerData(); - data.setGroupName(info.getGroupName()); - return data; - } - - public String getGroupName() { return groupName; } diff --git a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/heartbeat/SubscriptionData.java b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/heartbeat/SubscriptionData.java index c3976527..31bbfb2b 100644 --- a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/heartbeat/SubscriptionData.java +++ b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/heartbeat/SubscriptionData.java @@ -3,53 +3,31 @@ */ package com.alibaba.rocketmq.common.protocol.heartbeat; -import com.alibaba.rocketmq.common.protocol.MQProtos.ConsumerInfo; -import com.alibaba.rocketmq.common.protocol.MQProtos.SubscriptionInfo; +import java.util.HashSet; +import java.util.Set; /** - * @author vintage.wang@gmail.com shijia.wxr@taobao.com - * + * @author shijia.wxr */ public class SubscriptionData { public final static String SUB_ALL = "*"; private String topic; private String subString; - private String subNumfmt; - private boolean hasAndOperator; + private Set tagsSet = new HashSet(); + private Set codeSet = new HashSet(); + private long subVersion = System.currentTimeMillis(); public SubscriptionData() { + } - public SubscriptionData(String topic, String subString, String subNumfmt, boolean hasAndOperator) { + public SubscriptionData(String topic, String subString) { + super(); this.topic = topic; this.subString = subString; - this.subNumfmt = subNumfmt; - this.hasAndOperator = hasAndOperator; - } - - - public static SubscriptionData decode(SubscriptionInfo info) { - SubscriptionData data = new SubscriptionData(); - data.setTopic(info.getTopic()); - data.setSubString(info.getSubString()); - data.setSubNumfmt(info.getSubNumfmt()); - data.setHasAndOperator(info.getHasAndOperator()); - return data; - } - - - public SubscriptionInfo encode() { - SubscriptionInfo.Builder builder = SubscriptionInfo.newBuilder(); - - builder.setTopic(this.topic); - builder.setSubString(this.subString); - builder.setSubNumfmt(this.subNumfmt); - builder.setHasAndOperator(this.hasAndOperator); - - return builder.build(); } @@ -73,34 +51,91 @@ public void setSubString(String subString) { } - public String getSubNumfmt() { - return subNumfmt; + public Set getTagsSet() { + return tagsSet; + } + + + public void setTagsSet(Set tagsSet) { + this.tagsSet = tagsSet; + } + + + public long getSubVersion() { + return subVersion; } - public void setSubNumfmt(String subNumfmt) { - this.subNumfmt = subNumfmt; + public void setSubVersion(long subVersion) { + this.subVersion = subVersion; } - public boolean isHasAndOperator() { - return hasAndOperator; + public Set getCodeSet() { + return codeSet; } - public void setHasAndOperator(boolean hasAndOperator) { - this.hasAndOperator = hasAndOperator; + public void setCodeSet(Set codeSet) { + this.codeSet = codeSet; } - public static String getSubAll() { - return SUB_ALL; + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((codeSet == null) ? 0 : codeSet.hashCode()); + result = prime * result + ((subString == null) ? 0 : subString.hashCode()); + result = prime * result + (int) (subVersion ^ (subVersion >>> 32)); + result = prime * result + ((tagsSet == null) ? 0 : tagsSet.hashCode()); + result = prime * result + ((topic == null) ? 0 : topic.hashCode()); + return result; + } + + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + SubscriptionData other = (SubscriptionData) obj; + if (codeSet == null) { + if (other.codeSet != null) + return false; + } + else if (!codeSet.equals(other.codeSet)) + return false; + if (subString == null) { + if (other.subString != null) + return false; + } + else if (!subString.equals(other.subString)) + return false; + if (subVersion != other.subVersion) + return false; + if (tagsSet == null) { + if (other.tagsSet != null) + return false; + } + else if (!tagsSet.equals(other.tagsSet)) + return false; + if (topic == null) { + if (other.topic != null) + return false; + } + else if (!topic.equals(other.topic)) + return false; + return true; } @Override public String toString() { - return "SubscriptionData [topic=" + topic + ", subString=" + subString + ", subNumfmt=" + subNumfmt - + ", hasAndOperator=" + hasAndOperator + "]"; + return "SubscriptionData [topic=" + topic + ", subString=" + subString + ", tagsSet=" + tagsSet + + ", codeSet=" + codeSet + ", subVersion=" + subVersion + "]"; } } diff --git a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/mq.proto b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/mq.proto deleted file mode 100644 index 96f826bb..00000000 --- a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/mq.proto +++ /dev/null @@ -1,176 +0,0 @@ -// -// RocketMQͨЭ -// 2013-01-21 19:11:14 ļ V0.1 -// -import "remoting.proto"; -package rocketmq; -option optimize_for = SPEED; -option java_package = "com.alibaba.rocketmq.common.protocol"; -option java_outer_classname = "MQProtos"; - - -// RPC -enum MQRequestCode{ - SEND_MESSAGE = 10; // Broker Ϣ - PULL_MESSAGE = 11; // Broker Ϣ - QUERY_MESSAGE = 12; // Broker ѯϢ - - QUERY_BROKER_OFFSET = 13; // Broker ѯBroker Offset - QUERY_CONSUMER_OFFSET = 14; // Broker ѯConsumer Offset - UPDATE_CONSUMER_OFFSET = 15; // Broker Consumer Offset - - UPDATE_AND_CREATE_TOPIC = 17; // Broker »һTopic - DELETE_TOPIC = 19; // Broker ɾһTopic - GET_ALL_TOPIC_CONFIG = 21; // Broker ȡTopicãSlaveNamesrvMasterã - - GET_TOPIC_CONFIG_LIST = 22; // Broker ȡTopicãSlaveNamesrvMasterã - GET_TOPIC_NAME_LIST = 23; // Broker ȡTopicб - PULL_ALL_CONSUMER_OFFSET = 24; // Broker SlaveȡMasterConsumerѽ - UPDATE_BROKER_CONFIG = 25; // Broker Brokerϵ - GET_BROKER_CONFIG = 26; // Broker ȡBrokerϵ - TRIGGER_DELETE_FILES = 27; // Broker Brokerɾļ - GET_BROKER_RUNTIME_INFO = 28; // Broker ȡBrokerʱϢ - - SEARCH_OFFSET_BY_TIMESTAMP = 29; // Broker ʱѯеOffset - GET_MAX_OFFSET = 30; // Broker ѯOffset - GET_MIN_OFFSET = 31; // Broker ѯСOffset - GET_EARLIEST_MSG_STORETIME = 32; // Broker ѯϢӦʱ - VIEW_MESSAGE_BY_ID = 33; // Broker ϢIDѯϢ - - HEART_BEAT = 34; // Broker ClientClientע - UNREGISTER_CLIENT = 35; // Broker Clientע - - CONSUMER_SEND_MSG_BACK = 36; // Broker Consumer˵Ϣط - - END_TRANSACTION = 37; // Broker CommitRollback - - CHECK_TRANSACTION_STATE = 38; // Broker Producerز״̬ - - REGISTER_BROKER = 100; // Namesrv עһBrokerݶdz־ûģ򸲸 - UNREGISTER_BROKER = 101; // Namesrv жһBrokerݶdz־û - GET_BROKER_LIST = 102; // Namesrv ȡעBrokerб - REGISTER_ORDER_TOPIC = 103; // Namesrv עһϸ˳Topicݶdz־ûģ򸲸 - UNREGISTER_ORDER_TOPIC = 104; // Namesrv жһϸ˳Topicݶdz־û - GET_ORDER_TOPIC_LIST = 105; // Namesrv ȡעϸ˳Topicб - UPDATE_NAMESRV_CONFIG = 106; // Namesrv Namesrvϵ - GET_NAMESRV_CONFIG = 107; // Namesrv ȡNamesrvϵ - GET_NAMESRV_RUNTIME_INFO = 108; // Namesrv ȡNamesrvʱϢ - - GET_ROUTEINTO_BY_TOPIC = 109; // Namesrv TopicȡBroker Name(д) - // ProducerNamesrvǷ˳Ϣãһء - - SYNC_NAMESRV_RUNTIME_CONF = 110; // Namesrv ͬNamesrvڵʱtopic·Ϣ - REGISTER_BROKER_SINGLE = 111; // Namesrv NamesrvɢbrokerעϢ - UNREGISTER_BROKER_SINGLE = 112; // Namesrv NamesrvɢbrokerעϢ - REGISTER_ORDER_TOPIC_SINGLE = 113; // Namesrv Namesrvɢorder topicעϢ - UNREGISTER_ORDER_TOPIC_SINGLE = 114; // Namesrv Namesrvɢorder topicעϢ - -} - -// RPCӦ -enum MQResponseCode{ - FLUSH_DISK_TIMEOUT = 10; // Broker ˢ̳ʱ - SLAVE_NOT_AVAILABLE = 11; // Broker ͬ˫дSlave - FLUSH_SLAVE_TIMEOUT = 12; // Broker ͬ˫дȴSlaveӦʱ - MESSAGE_ILLEGAL = 13; // Broker ϢǷ - SERVICE_NOT_AVAILABLE = 14; // Broker, Namesrv 񲻿ãڹرջȨ - - VERSION_NOT_SUPPORTED = 15; // Broker, Namesrv 汾Ų֧ - NO_PERMISSION = 16; // Broker, Namesrv Ȩִд˲Ƿա - TOPIC_NOT_EXIST = 17; // Broker, Topic - TOPIC_EXIST_ALREADY = 18; // Broker, TopicѾڣTopic - PULL_NOT_FOUND = 19; // Broker ϢδҵOffsetOffsetOffset޶ӦϢ - PULL_RETRY_IMMEDIATELY = 20; // Broker ܱˣ֪ͨ - PULL_OFFSET_MOVED = 21; // Broker ϢOffsetϷ̫С̫ - QUERY_NOT_FOUND = 22; // Broker ѯϢδҵ - - - DELETE_INVALID_CONF = 100; // Namesrv ͬʱڵݲһ£ɾһµ - NOT_MERGE_CONF = 101; // Namesrv ڵ֮һû޸ - REGISTER_BROKER_FAIL = 102; // Namesrv עbrokerϢʧ - REGISTER_BROKER_TIMEOUT = 103; // Namesrv עbrokerϢʱ - REGISTER_ORDER_TOPIC_FAIL = 104; // Namesrv עorder topicʧ - REGISTER_ORDER_TOPIC_TIMEOUT = 105; // Namesrv עorder topicóʱ - UNREGISTER_BROKER_FAIL = 106; // Namesrv עbrokerϢʧ - UNREGISTER_BROKER_TIMEOUT = 107; // Namesrv עbrokerʱ - UNREGISTER_ORDER_TOPIC_TIMEOUT = 108; // Namesrv עorder topicóʱ - - TRANSACTION_SHOULD_COMMIT = 200; // Producer Ӧñύ - TRANSACTION_SHOULD_ROLLBACK = 201; // Producer Ӧñع - TRANSACTION_STATE_UNKNOW = 202; // Producer ״̬δ֪ - TRANSACTION_STATE_GROUP_WRONG = 203; // Producer ProducerGroup -} - -// -// Name Server Route -// -message BrokerInfo { - required string brokerName = 1; - - message BrokerAddr{ - required int64 id = 1; - required string addr = 2; - } - - repeated BrokerAddr brokerAddrs = 2; -} - -message QueueInfo{ - required string brokerName = 1; - required int32 readQueueNums = 2; - required int32 writeQueueNums = 3; - required int32 perm = 4; -} - -message TopicRouteInfo { - repeated QueueInfo queueInfos = 1; - repeated BrokerInfo brokerInfos = 2; - optional string orderTopicConf = 3; -} - -// -// Heart Beat -// -message ProducerInfo { - required string groupName = 1; -} - -message SubscriptionInfo { - required string topic = 1; - required string subString = 2; - required string subNumfmt = 3; - required bool hasAndOperator = 4; -} - -message ConsumerInfo { - required string groupName = 1; - required string consumeType = 2; - required string messageModel = 3; - repeated SubscriptionInfo subscriptionInfos = 4; -} - -message HeartbeatInfo { - required string clientID = 1; - repeated ProducerInfo producerInfos = 2; - repeated ConsumerInfo consumerInfos = 3; -} - -// TODO ʱʹ -message TopicQueuePair { - required string topic = 1; - repeated QueueInfo queueInfo = 2; -} - -// TODO ʱʹ -message BrokerDataPair { - required string brokerName = 1; - required BrokerInfo brokerInfo = 2; -} - -// TODO ʱʹ -message TopicRuntimeInfo { - repeated TopicQueuePair topicBrokers = 1; - required remoting.NVPairList topicOrderConfs = 2; - repeated BrokerDataPair brokers = 3; - required remoting.StringList brokerList = 4; -} diff --git a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/route/BrokerData.java b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/route/BrokerData.java index 08484760..09ae0688 100644 --- a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/route/BrokerData.java +++ b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/route/BrokerData.java @@ -5,17 +5,23 @@ import java.util.HashMap; +import com.alibaba.rocketmq.common.MixAll; + +/** + * @author shijia.wxr + * @since 2013-7-2 + */ public class BrokerData implements Comparable { private String brokerName; private HashMap brokerAddrs; /** - * ȻȡMasterûMasterSlave + * 优先获取Master,如果没有Master尝试找Slave */ - public String getOneBrokerAddr() { - String value = this.brokerAddrs.get(0); + public String selectBrokerAddr() { + String value = this.brokerAddrs.get(MixAll.MASTER_ID); if (null == value) { for (Long key : this.brokerAddrs.keySet()) { return this.brokerAddrs.get(key); @@ -89,6 +95,6 @@ public String toString() { @Override public int compareTo(BrokerData o) { - return this.brokerName.compareTo(o.getBrokerName()); + return this.brokerName.compareTo(o.getBrokerName()); } } diff --git a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/route/ObjectConverter.java b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/route/ObjectConverter.java deleted file mode 100644 index 325d0e4b..00000000 --- a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/route/ObjectConverter.java +++ /dev/null @@ -1,267 +0,0 @@ -/** - * $Id$ - */ -package com.alibaba.rocketmq.common.protocol.route; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Properties; -import java.util.Set; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.alibaba.rocketmq.common.TopicConfig; -import com.alibaba.rocketmq.common.namesrv.TopicRuntimeData; -import com.alibaba.rocketmq.common.protocol.MQProtos.BrokerDataPair; -import com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo; -import com.alibaba.rocketmq.common.protocol.MQProtos.BrokerInfo.BrokerAddr; -import com.alibaba.rocketmq.common.protocol.MQProtos.QueueInfo; -import com.alibaba.rocketmq.common.protocol.MQProtos.TopicQueuePair; -import com.alibaba.rocketmq.common.protocol.MQProtos.TopicRouteInfo; -import com.alibaba.rocketmq.common.protocol.MQProtos.TopicRuntimeInfo; -import com.alibaba.rocketmq.remoting.protocol.RemotingProtos; -import com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPair; -import com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPairList; -import com.alibaba.rocketmq.remoting.protocol.RemotingProtos.StringList; - - -/** - * @author lansheng.zj@taobao.com - */ -public class ObjectConverter { - - public static TopicRouteInfo topicRouteData2TopicRouteInfo(TopicRouteData topicRouteData) { - TopicRouteInfo.Builder topicRouteInfo = TopicRouteInfo.newBuilder(); - for (QueueData queueData : topicRouteData.getQueueDatas()) { - topicRouteInfo.addQueueInfos(queueData2QueueInfo(queueData)); - } - - for (BrokerData brokerData : topicRouteData.getBrokerDatas()) { - topicRouteInfo.addBrokerInfos(brokerData2BrokerInfo(brokerData)); - } - - topicRouteInfo.setOrderTopicConf(topicRouteData.getOrderTopicConf()); - - return topicRouteInfo.build(); - } - - - public static TopicRouteData topicRouteInfo2TopicRouteData(TopicRouteInfo topicRouteInfo) { - TopicRouteData topicRouteData = new TopicRouteData(); - List queueInfoList = topicRouteInfo.getQueueInfosList(); - List queueDataList = new ArrayList(); - for (QueueInfo queueInfo : queueInfoList) { - queueDataList.add(queueInfo2QueueData(queueInfo)); - } - - List brokerDataList = new ArrayList(); - List brokerInfoList = topicRouteInfo.getBrokerInfosList(); - for (BrokerInfo brokerInfo : brokerInfoList) { - brokerDataList.add(brokerInfo2BrokerData(brokerInfo)); - } - - topicRouteData.setQueueDatas(queueDataList); - topicRouteData.setBrokerDatas(brokerDataList); - topicRouteData.setOrderTopicConf(topicRouteInfo.getOrderTopicConf()); - - return topicRouteData; - } - - - public static QueueData queueInfo2QueueData(QueueInfo queueInfo) { - QueueData queueData = new QueueData(); - queueData.setBrokerName(queueInfo.getBrokerName()); - queueData.setReadQueueNums(queueInfo.getReadQueueNums()); - queueData.setWriteQueueNums(queueInfo.getWriteQueueNums()); - queueData.setPerm(queueInfo.getPerm()); - - return queueData; - } - - - public static QueueInfo queueData2QueueInfo(QueueData queueData) { - QueueInfo.Builder qb = QueueInfo.newBuilder(); - qb.setBrokerName(queueData.getBrokerName()); - qb.setPerm(queueData.getPerm()); - qb.setReadQueueNums(queueData.getReadQueueNums()); - qb.setWriteQueueNums(queueData.getWriteQueueNums()); - - return qb.build(); - } - - - public static BrokerData brokerInfo2BrokerData(BrokerInfo brokerInfo) { - BrokerData brokerData = new BrokerData(); - brokerData.setBrokerName(brokerInfo.getBrokerName()); - - HashMap brokerAddrs = new HashMap(); - for (BrokerAddr brokerAddr : brokerInfo.getBrokerAddrsList()) { - brokerAddrs.put(brokerAddr.getId(), brokerAddr.getAddr()); - } - - brokerData.setBrokerAddrs(brokerAddrs); - - return brokerData; - } - - - public static BrokerInfo brokerData2BrokerInfo(BrokerData brokerData) { - BrokerInfo.Builder bb = BrokerInfo.newBuilder(); - bb.setBrokerName(brokerData.getBrokerName()); - for (Entry entry : brokerData.getBrokerAddrs().entrySet()) { - BrokerAddr.Builder bab = BrokerAddr.newBuilder(); - bab.setId(entry.getKey()); - bab.setAddr(entry.getValue()); - bb.addBrokerAddrs(bab.build()); - } - return bb.build(); - } - - - public static Map nvPairList2HashMap(NVPairList nvPairList) { - HashMap map = new HashMap(); - for (RemotingProtos.NVPair nvPair : nvPairList.getFieldsList()) { - map.put(nvPair.getName(), nvPair.getValue()); - } - - return map; - } - - - public static NVPairList hashMap2NVPairList(Map map) { - NVPairList.Builder nvlb = NVPairList.newBuilder(); - int index = 0; - for (Entry entry : map.entrySet()) { - NVPair.Builder nvb = NVPair.newBuilder(); - nvb.setName(entry.getKey()); - nvb.setValue(entry.getValue()); - nvlb.addFields(index, nvb.build()); - } - - return nvlb.build(); - } - - - public static TopicRuntimeData topicRuntimeInfo2TopicRuntimeData(TopicRuntimeInfo topicRuntimeInfo) { - TopicRuntimeData topicRuntimeData = new TopicRuntimeData(); - for (TopicQueuePair topicQueuePair : topicRuntimeInfo.getTopicBrokersList()) { - List listQueueInfo = topicQueuePair.getQueueInfoList(); - List listQueueData = new ArrayList(); - for (QueueInfo queueInfo : listQueueInfo) { - listQueueData.add(queueInfo2QueueData(queueInfo)); - } - topicRuntimeData.getTopicBrokers().put(topicQueuePair.getTopic(), listQueueData); - } - - topicRuntimeData.setTopicOrderConfs(nvPairList2HashMap(topicRuntimeInfo.getTopicOrderConfs())); - - for (BrokerDataPair brokerDataPair : topicRuntimeInfo.getBrokersList()) { - topicRuntimeData.getBrokers().put(brokerDataPair.getBrokerName(), - brokerInfo2BrokerData(brokerDataPair.getBrokerInfo())); - } - - topicRuntimeData.setBrokerList(topicRuntimeInfo.getBrokerList().getNameList()); - - return topicRuntimeData; - } - - - public static StringList list2StringList(List list) { - StringList.Builder slb = StringList.newBuilder(); - for (String name : list) { - slb.addName(name); - } - return slb.build(); - } - - - public static TopicRuntimeInfo topicRuntimeData2TopicRuntimeInfo(TopicRuntimeData topicRuntimeData) { - TopicRuntimeInfo.Builder tri = TopicRuntimeInfo.newBuilder(); - for (Entry> entry : topicRuntimeData.getTopicBrokers().entrySet()) { - List queueDataList = entry.getValue(); - TopicQueuePair.Builder tqpb = TopicQueuePair.newBuilder(); - tqpb.setTopic(entry.getKey()); - for (QueueData queueData : queueDataList) { - tqpb.addQueueInfo(queueData2QueueInfo(queueData)); - } - tri.addTopicBrokers(tqpb.build()); - } - - tri.setTopicOrderConfs(hashMap2NVPairList(topicRuntimeData.getTopicOrderConfs())); - - for (Entry entry : topicRuntimeData.getBrokers().entrySet()) { - BrokerDataPair.Builder bdpb = BrokerDataPair.newBuilder(); - bdpb.setBrokerName(entry.getKey()); - bdpb.setBrokerInfo(brokerData2BrokerInfo(entry.getValue())); - tri.addBrokers(bdpb.build()); - } - - tri.setBrokerList(list2StringList(topicRuntimeData.getBrokerList())); - - return tri.build(); - } - - - public static boolean equals(List l1, List l2) { - if (l1 == l2) - return true; - if (null == l1 || null == l2) - return false; - if (l1.size() != l2.size()) - return false; - - for (T e : l1) { - boolean equal = false; - for (T a : l2) { - equal = e.equals(a); - if (equal) - break; - } - if (!equal) - return false; - } - return true; - } - - - public static boolean equals(Map m1, Map m2) { - if (m1 == m2) - return true; - if (null == m1 || null == m2) - return false; - if (m1.size() != m2.size()) - return false; - - for (Entry entry : m1.entrySet()) { - V newV = m2.get(entry.getKey()); - if (!entry.getValue().equals(newV)) - return false; - } - - return true; - } - - - public static Map props2TopicConfigTable(Properties prop, Logger log) { - Map topicConfigTable = new HashMap(); - Set keyset = prop.keySet(); - for (Object object : keyset) { - String propValue = prop.getProperty(object.toString()); - if (propValue != null) { - TopicConfig tc = new TopicConfig(null); - if (tc.decode(propValue)) { - topicConfigTable.put(tc.getTopicName(), tc); - if (null != log) - log.info("load topic config OK, " + tc); - } - } - } - - return topicConfigTable; - } - -} diff --git a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/route/QueueData.java b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/route/QueueData.java index 2f9efab7..b100cfd1 100644 --- a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/route/QueueData.java +++ b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/route/QueueData.java @@ -89,8 +89,8 @@ else if (!brokerName.equals(other.brokerName)) @Override public String toString() { - return "QueueData [brokerName=" + brokerName + ", readQueueNums=" + readQueueNums + ", writeQueueNums=" - + writeQueueNums + ", perm=" + perm + "]"; + return "QueueData [brokerName=" + brokerName + ", readQueueNums=" + readQueueNums + + ", writeQueueNums=" + writeQueueNums + ", perm=" + perm + "]"; } diff --git a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/route/TopicRouteData.java b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/route/TopicRouteData.java index 0af1f411..ae0b72b1 100644 --- a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/route/TopicRouteData.java +++ b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/protocol/route/TopicRouteData.java @@ -3,35 +3,38 @@ */ package com.alibaba.rocketmq.common.protocol.route; +import java.util.ArrayList; import java.util.List; -import com.alibaba.rocketmq.common.protocol.MQProtos.TopicRouteInfo; -import com.google.protobuf.InvalidProtocolBufferException; +import com.alibaba.rocketmq.remoting.protocol.RemotingSerializable; /** - * Topic·ݣName Serverȡ - * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * Topic路由数据,从Name Server获取 * + * @author shijia.wxr */ -public class TopicRouteData { - public static final String SEP = ","; +public class TopicRouteData extends RemotingSerializable { + private String orderTopicConf; private List queueDatas; private List brokerDatas; - private String orderTopicConf; + public TopicRouteData cloneTopicRouteData() { + TopicRouteData topicRouteData = new TopicRouteData(); + topicRouteData.setQueueDatas(new ArrayList()); + topicRouteData.setBrokerDatas(new ArrayList()); + topicRouteData.setOrderTopicConf(this.orderTopicConf); - public byte[] encode() { - TopicRouteInfo topicRouteInfo = ObjectConverter.topicRouteData2TopicRouteInfo(this); - return topicRouteInfo.toByteArray(); - } + if (this.queueDatas != null) { + topicRouteData.getQueueDatas().addAll(this.queueDatas); + } + if (this.brokerDatas != null) { + topicRouteData.getBrokerDatas().addAll(this.brokerDatas); + } - public static TopicRouteData decode(byte[] data) throws InvalidProtocolBufferException { - TopicRouteInfo topicRouteInfo = TopicRouteInfo.parseFrom(data); - return ObjectConverter.topicRouteInfo2TopicRouteData(topicRouteInfo); + return topicRouteData; } @@ -105,4 +108,11 @@ else if (!queueDatas.equals(other.queueDatas)) return false; return true; } + + + @Override + public String toString() { + return "TopicRouteData [queueDatas=" + queueDatas + ", brokerDatas=" + brokerDatas + + ", orderTopicConf=" + orderTopicConf + "]"; + } } diff --git a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/running/RunningStats.java b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/running/RunningStats.java new file mode 100644 index 00000000..b4e6737c --- /dev/null +++ b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/running/RunningStats.java @@ -0,0 +1,24 @@ +/** + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.rocketmq.common.running; + +public enum RunningStats { + commitLogMaxOffset, + commitLogMinOffset, + commitLogDiskRatio, + consumeQueueDiskRatio, + scheduleMessageOffset, +} diff --git a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/subscription/SubscriptionGroupConfig.java b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/subscription/SubscriptionGroupConfig.java new file mode 100644 index 00000000..6798e799 --- /dev/null +++ b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/subscription/SubscriptionGroupConfig.java @@ -0,0 +1,167 @@ +package com.alibaba.rocketmq.common.subscription; + +import com.alibaba.rocketmq.common.MixAll; + + +/** + * @author shijia.wxr + * @since 2013-6-18 + */ +public class SubscriptionGroupConfig { + // 订阅组名 + private String groupName; + // 消费功能是否开启 + private boolean consumeEnable = true; + // 是否允许从队列最小位置开始消费,线上默认会设置为false + private boolean consumeFromMinEnable = true; + // 是否允许广播方式消费 + private boolean consumeBroadcastEnable = true; + // 消费失败的消息放到一个重试队列,每个订阅组配置几个重试队列 + private int retryQueueNums = 1; + // 重试消费最大次数,超过则投递到死信队列,不再投递,并报警 + private int retryMaxTimes = 5; + // 从哪个Broker开始消费 + private long brokerId = MixAll.MASTER_ID; + // 发现消息堆积后,将Consumer的消费请求重定向到另外一台Slave机器 + private long whichBrokerWhenConsumeSlowly = 1; + + + public String getGroupName() { + return groupName; + } + + + public void setGroupName(String groupName) { + this.groupName = groupName; + } + + + public boolean isConsumeEnable() { + return consumeEnable; + } + + + public void setConsumeEnable(boolean consumeEnable) { + this.consumeEnable = consumeEnable; + } + + + public boolean isConsumeFromMinEnable() { + return consumeFromMinEnable; + } + + + public void setConsumeFromMinEnable(boolean consumeFromMinEnable) { + this.consumeFromMinEnable = consumeFromMinEnable; + } + + + public boolean isConsumeBroadcastEnable() { + return consumeBroadcastEnable; + } + + + public void setConsumeBroadcastEnable(boolean consumeBroadcastEnable) { + this.consumeBroadcastEnable = consumeBroadcastEnable; + } + + + public int getRetryQueueNums() { + return retryQueueNums; + } + + + public void setRetryQueueNums(int retryQueueNums) { + this.retryQueueNums = retryQueueNums; + } + + + public int getRetryMaxTimes() { + return retryMaxTimes; + } + + + public void setRetryMaxTimes(int retryMaxTimes) { + this.retryMaxTimes = retryMaxTimes; + } + + + public long getBrokerId() { + return brokerId; + } + + + public void setBrokerId(long brokerId) { + this.brokerId = brokerId; + } + + + public long getWhichBrokerWhenConsumeSlowly() { + return whichBrokerWhenConsumeSlowly; + } + + + public void setWhichBrokerWhenConsumeSlowly(long whichBrokerWhenConsumeSlowly) { + this.whichBrokerWhenConsumeSlowly = whichBrokerWhenConsumeSlowly; + } + + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + (int) (brokerId ^ (brokerId >>> 32)); + result = prime * result + (consumeBroadcastEnable ? 1231 : 1237); + result = prime * result + (consumeEnable ? 1231 : 1237); + result = prime * result + (consumeFromMinEnable ? 1231 : 1237); + result = prime * result + ((groupName == null) ? 0 : groupName.hashCode()); + result = prime * result + retryMaxTimes; + result = prime * result + retryQueueNums; + result = + prime * result + (int) (whichBrokerWhenConsumeSlowly ^ (whichBrokerWhenConsumeSlowly >>> 32)); + return result; + } + + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + SubscriptionGroupConfig other = (SubscriptionGroupConfig) obj; + if (brokerId != other.brokerId) + return false; + if (consumeBroadcastEnable != other.consumeBroadcastEnable) + return false; + if (consumeEnable != other.consumeEnable) + return false; + if (consumeFromMinEnable != other.consumeFromMinEnable) + return false; + if (groupName == null) { + if (other.groupName != null) + return false; + } + else if (!groupName.equals(other.groupName)) + return false; + if (retryMaxTimes != other.retryMaxTimes) + return false; + if (retryQueueNums != other.retryQueueNums) + return false; + if (whichBrokerWhenConsumeSlowly != other.whichBrokerWhenConsumeSlowly) + return false; + return true; + } + + + @Override + public String toString() { + return "SubscriptionGroupConfig [groupName=" + groupName + ", consumeEnable=" + consumeEnable + + ", consumeFromMinEnable=" + consumeFromMinEnable + ", consumeBroadcastEnable=" + + consumeBroadcastEnable + ", retryQueueNums=" + retryQueueNums + ", retryMaxTimes=" + + retryMaxTimes + ", brokerId=" + brokerId + ", whichBrokerWhenConsumeSlowly=" + + whichBrokerWhenConsumeSlowly + "]"; + } +} diff --git a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/sysflag/MessageSysFlag.java b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/sysflag/MessageSysFlag.java index f908da1f..bd81ea04 100644 --- a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/sysflag/MessageSysFlag.java +++ b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/sysflag/MessageSysFlag.java @@ -1,11 +1,22 @@ /** - * $Id: MessageSysFlag.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.common.sysflag; /** - * @author vintage.wang@gmail.com shijia.wxr@taobao.com - * + * @author shijia.wxr */ public class MessageSysFlag { /** @@ -16,7 +27,7 @@ public class MessageSysFlag { /** * 7 6 5 4 3 2 1 0
- * SysFlag أ23 + * SysFlag 事务相关,从左属,2与3 */ public final static int TransactionNotType = (0x0 << 2); public final static int TransactionPreparedType = (0x1 << 2); diff --git a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/sysflag/PullSysFlag.java b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/sysflag/PullSysFlag.java index 9c331b1b..23adf330 100644 --- a/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/sysflag/PullSysFlag.java +++ b/rocketmq-common/src/main/java/com/alibaba/rocketmq/common/sysflag/PullSysFlag.java @@ -1,13 +1,24 @@ /** - * $Id: PullSysFlag.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.common.sysflag; /** - * Pullӿõflag - * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * Pull接口用到的flag定义 * + * @author shijia.wxr */ public class PullSysFlag { private final static int FLAG_COMMIT_OFFSET = 0x1 << 0; @@ -15,7 +26,8 @@ public class PullSysFlag { private final static int FLAG_SUBSCRIPTION = 0x1 << 2; - public static int buildSysFlag(final boolean commitOffset, final boolean suspend, final boolean subscription) { + public static int buildSysFlag(final boolean commitOffset, final boolean suspend, + final boolean subscription) { int flag = 0; if (commitOffset) { diff --git a/rocketmq-common/src/test/java/com/alibaba/rocketmq/common/RemotingUtilTest.java b/rocketmq-common/src/test/java/com/alibaba/rocketmq/common/RemotingUtilTest.java new file mode 100644 index 00000000..30e92887 --- /dev/null +++ b/rocketmq-common/src/test/java/com/alibaba/rocketmq/common/RemotingUtilTest.java @@ -0,0 +1,29 @@ +/** + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.rocketmq.common; + +import org.junit.Test; + +import com.alibaba.rocketmq.remoting.common.RemotingUtil; + + +public class RemotingUtilTest { + @Test + public void test() throws Exception { + String a = RemotingUtil.getLocalAddress(); + System.out.println(a); + } +} diff --git a/rocketmq-common/src/test/java/com/alibaba/rocketmq/common/TopicRuntimeDataTest.java b/rocketmq-common/src/test/java/com/alibaba/rocketmq/common/TopicRuntimeDataTest.java deleted file mode 100644 index d9ab1748..00000000 --- a/rocketmq-common/src/test/java/com/alibaba/rocketmq/common/TopicRuntimeDataTest.java +++ /dev/null @@ -1,127 +0,0 @@ -package com.alibaba.rocketmq.common; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; - -import org.junit.Assert; -import org.junit.Test; - -import com.alibaba.rocketmq.common.namesrv.TopicRuntimeData; -import com.alibaba.rocketmq.common.protocol.route.BrokerData; -import com.alibaba.rocketmq.common.protocol.route.QueueData; - - -public class TopicRuntimeDataTest { - - @Test - public void testEncode() throws Exception { - TopicRuntimeData topicRuntimeData = create(); - byte[] data = topicRuntimeData.encode(); - TopicRuntimeData serial = TopicRuntimeData.decode(data); - - Assert.assertTrue(topicRuntimeData.equals(serial)); - } - - @Test - public void testEncodeSpecific() throws Exception { - TopicRuntimeData topicRuntimeData = createSpecific(); - byte[] data = topicRuntimeData.encodeSpecific(); - TopicRuntimeData serial = TopicRuntimeData.decode(data); - - Assert.assertTrue(topicRuntimeData.equals(serial)); - } - - - private TopicRuntimeData createSpecific() { - TopicRuntimeData data = new TopicRuntimeData(); - - data.getTopicOrderConfs().put("topic-1", - "topic.num.DAILY-UIC-USERS-EXTRA=105:4;106:4;topic.num.andor-applye-test=100:2;101:2"); - - data.getBrokerList().add("10.23.12.12:8123"); - data.getBrokerList().add("10.23.12.13:8123"); - data.getBrokerList().add("10.23.12.14:8123"); - data.getBrokerList().add("10.23.12.15:8123"); - - return data; - } - - - private TopicRuntimeData create() { - TopicRuntimeData data = new TopicRuntimeData(); - QueueData queueData1 = new QueueData(); - queueData1.setBrokerName("broker-1"); - queueData1.setPerm(4); - queueData1.setReadQueueNums(4); - queueData1.setWriteQueueNums(4); - - QueueData queueData2 = new QueueData(); - queueData2.setBrokerName("broker-2"); - queueData2.setPerm(4); - queueData2.setReadQueueNums(4); - queueData2.setWriteQueueNums(4); - - QueueData queueData3 = new QueueData(); - queueData3.setBrokerName("broker-3"); - queueData3.setPerm(4); - queueData3.setReadQueueNums(4); - queueData3.setWriteQueueNums(4); - - QueueData queueData4 = new QueueData(); - queueData4.setBrokerName("broker-4"); - queueData4.setPerm(4); - queueData4.setReadQueueNums(4); - queueData4.setWriteQueueNums(4); - - List queueDatas1 = new ArrayList(); - queueDatas1.add(queueData1); - queueDatas1.add(queueData2); - - List queueDatas2 = new ArrayList(); - queueDatas2.add(queueData3); - queueDatas2.add(queueData4); - - data.getTopicBrokers().put("topic-1", queueDatas1); - data.getTopicBrokers().put("topic-2", queueDatas2); - - data.getTopicOrderConfs().put("topic-1", - "topic.num.DAILY-UIC-USERS-EXTRA=105:4;106:4;topic.num.andor-applye-test=100:2;101:2"); - - BrokerData broker1 = new BrokerData(); - broker1.setBrokerName("broker-1"); - HashMap brokerAddrs1 = new HashMap(); - brokerAddrs1.put(0L, "10.23.12.12:8123"); - broker1.setBrokerAddrs(brokerAddrs1); - - BrokerData broker2 = new BrokerData(); - broker2.setBrokerName("broker-2"); - HashMap brokerAddrs2 = new HashMap(); - brokerAddrs2.put(0L, "10.23.12.13:8123"); - broker2.setBrokerAddrs(brokerAddrs2); - - BrokerData broker3 = new BrokerData(); - broker3.setBrokerName("broker-3"); - HashMap brokerAddrs3 = new HashMap(); - brokerAddrs3.put(0L, "10.23.12.14:8123"); - broker3.setBrokerAddrs(brokerAddrs3); - - BrokerData broker4 = new BrokerData(); - broker4.setBrokerName("broker-4"); - HashMap brokerAddrs4 = new HashMap(); - //brokerAddrs4.put(0L, "10.23.12.15:8123"); - broker4.setBrokerAddrs(brokerAddrs4); - - data.getBrokers().put("broker-1", broker1); - data.getBrokers().put("broker-2", broker2); - data.getBrokers().put("broker-3", broker3); - data.getBrokers().put("broker-4", broker4); - - data.getBrokerList().add("10.23.12.12:8123"); - data.getBrokerList().add("10.23.12.13:8123"); - data.getBrokerList().add("10.23.12.14:8123"); - data.getBrokerList().add("10.23.12.15:8123"); - - return data; - } -} diff --git a/rocketmq-common/src/test/java/com/alibaba/rocketmq/common/UtilAllTest.java b/rocketmq-common/src/test/java/com/alibaba/rocketmq/common/UtilAllTest.java index d12cbadc..b97f03ee 100644 --- a/rocketmq-common/src/test/java/com/alibaba/rocketmq/common/UtilAllTest.java +++ b/rocketmq-common/src/test/java/com/alibaba/rocketmq/common/UtilAllTest.java @@ -1,6 +1,6 @@ package com.alibaba.rocketmq.common; -import static org.junit.Assert.*; +import static org.junit.Assert.assertTrue; import java.net.URL; import java.util.Properties; @@ -10,54 +10,6 @@ public class UtilAllTest { - class DemoConfig { - private int demoWidth = 0; - private int demoLength = 0; - private boolean demoOK = false; - private String demoName = "haha"; - - - public int getDemoWidth() { - return demoWidth; - } - - - public void setDemoWidth(int demoWidth) { - this.demoWidth = demoWidth; - } - - - public int getDemoLength() { - return demoLength; - } - - - public void setDemoLength(int demoLength) { - this.demoLength = demoLength; - } - - - public boolean isDemoOK() { - return demoOK; - } - - - public void setDemoOK(boolean demoOK) { - this.demoOK = demoOK; - } - - - public String getDemoName() { - return demoName; - } - - - public void setDemoNfieldame(String demoName) { - this.demoName = demoName; - } - } - - @Test public void test_a() { URL url = this.getClass().getProtectionDomain().getCodeSource().getLocation(); @@ -73,12 +25,6 @@ public void test_resetClassProperties() { } - @Test - public void test_printClassProperties() { - DemoConfig demoConfig = new DemoConfig(); - } - - @Test public void test_properties2String() { DemoConfig demoConfig = new DemoConfig(); @@ -87,15 +33,9 @@ public void test_properties2String() { } - @Test - public void test_getTotalPhysicalMemorySize() { - System.out.println(MixAll.TotalPhysicalMemorySize); - } - - @Test public void test_timeMillisToHumanString() { - System.out.println(UtilALl.timeMillisToHumanString()); + System.out.println(UtilAll.timeMillisToHumanString()); } @@ -109,7 +49,7 @@ public void test_isPropertiesEqual() { p2.setProperty("a", "1"); p2.setProperty("b", "2"); - //p2.setProperty("c", "3"); + // p2.setProperty("c", "3"); assertTrue(MixAll.isPropertiesEqual(p1, p2)); } @@ -117,9 +57,85 @@ public void test_isPropertiesEqual() { @Test public void test_getpid() { - int pid = UtilALl.getPid(); + int pid = UtilAll.getPid(); System.out.println("PID = " + pid); assertTrue(pid > 0); } + + + @Test + public void test_isBlank() { + { + boolean result = UtilAll.isBlank("Hello "); + assertTrue(result); + } + + { + boolean result = UtilAll.isBlank(" Hello"); + assertTrue(result); + } + + { + boolean result = UtilAll.isBlank("He llo"); + assertTrue(result); + } + + { + boolean result = UtilAll.isBlank(" "); + assertTrue(result); + } + + { + boolean result = UtilAll.isBlank("Hello"); + assertTrue(!result); + } + } + + class DemoConfig { + private int demoWidth = 0; + private int demoLength = 0; + private boolean demoOK = false; + private String demoName = "haha"; + + + public int getDemoWidth() { + return demoWidth; + } + + + public void setDemoWidth(int demoWidth) { + this.demoWidth = demoWidth; + } + + + public int getDemoLength() { + return demoLength; + } + + + public void setDemoLength(int demoLength) { + this.demoLength = demoLength; + } + + + public boolean isDemoOK() { + return demoOK; + } + + + public void setDemoOK(boolean demoOK) { + this.demoOK = demoOK; + } + + + public String getDemoName() { + return demoName; + } + + + public void setDemoNfieldame(String demoName) { + this.demoName = demoName; + } + } } diff --git a/rocketmq-common/src/test/java/com/alibaba/rocketmq/common/filter/FilterAPITest.java b/rocketmq-common/src/test/java/com/alibaba/rocketmq/common/filter/FilterAPITest.java new file mode 100644 index 00000000..0521a64c --- /dev/null +++ b/rocketmq-common/src/test/java/com/alibaba/rocketmq/common/filter/FilterAPITest.java @@ -0,0 +1,20 @@ +package com.alibaba.rocketmq.common.filter; + +import org.junit.Test; + +import com.alibaba.rocketmq.common.protocol.heartbeat.SubscriptionData; + + +/** + * @author shijia.wxr + * @since 2013-6-18 + */ +public class FilterAPITest { + + @Test + public void testBuildSubscriptionData() throws Exception { + SubscriptionData subscriptionData = + FilterAPI.buildSubscriptionData("TestTopic", "TAG1 || Tag2 || tag3"); + System.out.println(subscriptionData); + } +} diff --git a/rocketmq-common/src/test/java/com/alibaba/rocketmq/common/filter/PolishExprTest.java b/rocketmq-common/src/test/java/com/alibaba/rocketmq/common/filter/PolishExprTest.java index b8c797ce..22ee2457 100644 --- a/rocketmq-common/src/test/java/com/alibaba/rocketmq/common/filter/PolishExprTest.java +++ b/rocketmq-common/src/test/java/com/alibaba/rocketmq/common/filter/PolishExprTest.java @@ -6,6 +6,9 @@ import org.junit.Test; +import com.alibaba.rocketmq.common.filter.impl.Op; +import com.alibaba.rocketmq.common.filter.impl.PolishExpr; + /** * @auther lansheng.zj@taobao.com diff --git a/rocketmq-common/src/test/java/com/alibaba/rocketmq/common/protocol/MQProtosHelperTest.java b/rocketmq-common/src/test/java/com/alibaba/rocketmq/common/protocol/MQProtosHelperTest.java index 5b173e19..e535ac8d 100644 --- a/rocketmq-common/src/test/java/com/alibaba/rocketmq/common/protocol/MQProtosHelperTest.java +++ b/rocketmq-common/src/test/java/com/alibaba/rocketmq/common/protocol/MQProtosHelperTest.java @@ -1,8 +1,7 @@ package com.alibaba.rocketmq.common.protocol; /** - * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * @author shijia.wxr */ public class MQProtosHelperTest { diff --git a/rocketmq-common/src/test/java/com/alibaba/rocketmq/common/protocol/heartbeat/HeartbeatTest.java b/rocketmq-common/src/test/java/com/alibaba/rocketmq/common/protocol/heartbeat/HeartbeatTest.java deleted file mode 100644 index ddbb5204..00000000 --- a/rocketmq-common/src/test/java/com/alibaba/rocketmq/common/protocol/heartbeat/HeartbeatTest.java +++ /dev/null @@ -1,57 +0,0 @@ -/** - * $Id$ - */ -package com.alibaba.rocketmq.common.protocol.heartbeat; - -import static org.junit.Assert.*; - -import org.junit.Test; - -import com.google.protobuf.InvalidProtocolBufferException; - - -/** - * @author vintage.wang@gmail.com shijia.wxr@taobao.com - */ -public class HeartbeatTest { - @Test - public void test_encode_decode() throws InvalidProtocolBufferException { - HeartbeatData heartbeatData = new HeartbeatData(); - heartbeatData.setClientID("id100"); - - // producer - for (int i = 0; i < 3; i++) { - ProducerData data = new ProducerData(); - data.setGroupName("producer_group" + i); - heartbeatData.getProducerDataSet().add(data); - } - - // consumer - for (int i = 0; i < 3; i++) { - ConsumerData data = new ConsumerData(); - data.setGroupName("consumer_group" + i); - data.setConsumeType(ConsumeType.CONSUME_ACTIVELY); - data.setMessageModel(MessageModel.CLUSTERING); - - for (int k = 0; k < 3; k++) { - SubscriptionData sub = new SubscriptionData(); - sub.setHasAndOperator(false); - sub.setSubNumfmt("1 || 2 || 3"); - sub.setTopic("HelloTopic"); - sub.setSubString("A || B ||C"); - data.getSubscriptionDataSet().add(sub); - } - - heartbeatData.getConsumerDataSet().add(data); - } - - byte[] data = heartbeatData.encode(); - - assertTrue(data != null); - - HeartbeatData heartbeatDataDecode = HeartbeatData.decode(data); - - System.out.println(heartbeatDataDecode); - } - -} diff --git a/rocketmq-console/pom.xml b/rocketmq-console/pom.xml deleted file mode 100644 index 64263dc9..00000000 --- a/rocketmq-console/pom.xml +++ /dev/null @@ -1,32 +0,0 @@ - - - com.alibaba.rocketmq - rocketmq-all - 3.0.0-SNAPSHOT - - - 4.0.0 - jar - com.alibaba.rocketmq - rocketmq-console - rocketmq-console ${project.version} - - - - junit - junit - test - - - ${project.groupId} - rocketmq-client - - - org.eclipse.jetty - jetty-server - jar - compile - - - diff --git a/rocketmq-console/src/main/java/com/alibaba/rocketmq/console/ConsoleConfig.java b/rocketmq-console/src/main/java/com/alibaba/rocketmq/console/ConsoleConfig.java deleted file mode 100644 index 90519728..00000000 --- a/rocketmq-console/src/main/java/com/alibaba/rocketmq/console/ConsoleConfig.java +++ /dev/null @@ -1,58 +0,0 @@ -/** - * $Id: ConsoleConfig.java 1839 2013-05-16 02:12:02Z shijia.wxr $ - */ -package com.alibaba.rocketmq.console; - -import com.alibaba.rocketmq.common.MixAll; - - -/** - * @author vintage.wang@gmail.com shijia.wxr@taobao.com - * - */ -public class ConsoleConfig { - private String rocketmqHome = System.getenv(MixAll.ROCKETMQ_HOME_ENV); - private String namesrvAddr = null; - private String webRootPath; - private int listenPort = 8888; - - - public String getRocketmqHome() { - return rocketmqHome; - } - - - public void setRocketmqHome(String rocketmqHome) { - this.rocketmqHome = rocketmqHome; - } - - - public String getNamesrvAddr() { - return namesrvAddr; - } - - - public void setNamesrvAddr(String namesrvAddr) { - this.namesrvAddr = namesrvAddr; - } - - - public int getListenPort() { - return listenPort; - } - - - public void setListenPort(int listenPort) { - this.listenPort = listenPort; - } - - - public String getWebRootPath() { - return webRootPath; - } - - - public void setWebRootPath(String webRootPath) { - this.webRootPath = webRootPath; - } -} diff --git a/rocketmq-console/src/main/java/com/alibaba/rocketmq/console/ConsoleController.java b/rocketmq-console/src/main/java/com/alibaba/rocketmq/console/ConsoleController.java deleted file mode 100644 index 44deaf5c..00000000 --- a/rocketmq-console/src/main/java/com/alibaba/rocketmq/console/ConsoleController.java +++ /dev/null @@ -1,53 +0,0 @@ -/** - * $Id: ConsoleController.java 1831 2013-05-16 01:39:51Z shijia.wxr $ - */ -package com.alibaba.rocketmq.console; - -import org.eclipse.jetty.server.Server; - -import com.alibaba.rocketmq.console.http.ConsoleJettyHander; - - -/** - * @author vintage.wang@gmail.com shijia.wxr@taobao.com - */ -public class ConsoleController { - private final ConsoleConfig consoleConfig; - private final Server jettyServer; - private final ConsoleJettyHander consoleJettyHander; - - - public ConsoleController(final ConsoleConfig consoleConfig) { - this.consoleConfig = consoleConfig; - this.consoleJettyHander = new ConsoleJettyHander(); - this.jettyServer = this.createJettyServer(); - } - - - private Server createJettyServer() { - Server server = new Server(this.consoleConfig.getListenPort()); - server.setHandler(this.consoleJettyHander); - - return server; - } - - - public void start() throws Exception { - this.jettyServer.start(); - } - - - public void shutdown() { - try { - this.jettyServer.stop(); - } - catch (Exception e) { - e.printStackTrace(); - } - } - - - public ConsoleJettyHander getConsoleJettyHander() { - return consoleJettyHander; - } -} diff --git a/rocketmq-console/src/main/java/com/alibaba/rocketmq/console/ConsoleStartup.java b/rocketmq-console/src/main/java/com/alibaba/rocketmq/console/ConsoleStartup.java deleted file mode 100644 index f850f00e..00000000 --- a/rocketmq-console/src/main/java/com/alibaba/rocketmq/console/ConsoleStartup.java +++ /dev/null @@ -1,127 +0,0 @@ -/** - * $Id: ConsoleStartup.java 1839 2013-05-16 02:12:02Z shijia.wxr $ - */ -package com.alibaba.rocketmq.console; - -import java.io.BufferedInputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.InputStream; -import java.util.Properties; -import java.util.concurrent.atomic.AtomicInteger; - -import org.apache.commons.cli.CommandLine; -import org.apache.commons.cli.Option; -import org.apache.commons.cli.Options; -import org.apache.commons.cli.PosixParser; -import org.slf4j.Logger; - -import com.alibaba.rocketmq.common.MixAll; -import com.alibaba.rocketmq.common.MQVersion; -import com.alibaba.rocketmq.remoting.protocol.RemotingCommand; - - -/** - * Broker - * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com - */ -public class ConsoleStartup { - - public static Options buildCommandlineOptions(final Options options) { - Option opt = new Option("c", "configFile", true, "Console config properties file"); - opt.setRequired(false); - options.addOption(opt); - - opt = new Option("p", "printConfigItem", false, "Print all config item"); - opt.setRequired(false); - options.addOption(opt); - - return options; - } - - - public static void main(String[] args) { - // õǰ汾ţÿη汾ʱҪ޸CurrentVersion - System.setProperty(RemotingCommand.RemotingVersionKey, Integer.toString(MQVersion.CurrentVersion)); - - try { - // - Options options = MixAll.buildCommandlineOptions(new Options()); - final CommandLine commandLine = - MixAll.parseCmdLine("mqconsole", args, buildCommandlineOptions(options), new PosixParser()); - if (null == commandLine) { - System.exit(-1); - return; - } - - // ʼļ - final ConsoleConfig consoleConfig = new ConsoleConfig(); - - // ӡĬ - if (commandLine.hasOption('p')) { - MixAll.printObjectProperties(null, consoleConfig); - System.exit(0); - } - - // ָļ - if (commandLine.hasOption('c')) { - String file = commandLine.getOptionValue('c'); - if (file != null) { - InputStream in = new BufferedInputStream(new FileInputStream(file)); - Properties properties = new Properties(); - properties.load(in); - MixAll.properties2Object(properties, consoleConfig); - - System.out.println("load config properties file OK, " + file); - } - } - - MixAll.properties2Object(MixAll.commandLine2Properties(commandLine), consoleConfig); - - if (null == consoleConfig.getRocketmqHome()) { - System.out.println("Please set the " + MixAll.ROCKETMQ_HOME_ENV - + " variable in your environment to match the location of the RocketMQ installation"); - System.exit(-2); - } - - // ò - consoleConfig.setWebRootPath(consoleConfig.getRocketmqHome() + File.separator + "webroot"); - - final Logger log = null; - - // ӡ - MixAll.printObjectProperties(log, consoleConfig); - - // ʼƶ - final ConsoleController controller = new ConsoleController(consoleConfig); - - Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() { - private volatile boolean hasShutdown = false; - private AtomicInteger shutdownTimes = new AtomicInteger(0); - - - @Override - public void run() { - synchronized (this) { - log.info("shutdown hook was invoked, " + this.shutdownTimes.incrementAndGet()); - if (!this.hasShutdown) { - this.hasShutdown = true; - long begineTime = System.currentTimeMillis(); - controller.shutdown(); - long consumingTimeTotal = System.currentTimeMillis() - begineTime; - log.info("shutdown hook over, consuming time total(ms): " + consumingTimeTotal); - } - } - } - }, "ShutdownHook")); - - // ƶ - controller.start(); - } - catch (Throwable e) { - e.printStackTrace(); - System.exit(-1); - } - } -} diff --git a/rocketmq-console/src/main/java/com/alibaba/rocketmq/console/http/ConsoleJettyHander.java b/rocketmq-console/src/main/java/com/alibaba/rocketmq/console/http/ConsoleJettyHander.java deleted file mode 100644 index 0f8f7fcc..00000000 --- a/rocketmq-console/src/main/java/com/alibaba/rocketmq/console/http/ConsoleJettyHander.java +++ /dev/null @@ -1,29 +0,0 @@ -/** - * $Id: ConsoleJettyHander.java 1831 2013-05-16 01:39:51Z shijia.wxr $ - */ -package com.alibaba.rocketmq.console.http; - -import java.io.IOException; - -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.eclipse.jetty.server.Request; -import org.eclipse.jetty.server.handler.AbstractHandler; - - -/** - * @author vintage.wang@gmail.com shijia.wxr@taobao.com - * - */ -public class ConsoleJettyHander extends AbstractHandler { - - @Override - public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) - throws IOException, ServletException { - System.out.println("---------------------------------------------------"); - System.out.println(target); - System.out.println(baseRequest); - } -} diff --git a/rocketmq-example/pom.xml b/rocketmq-example/pom.xml index b1517c60..a6cefa0a 100644 --- a/rocketmq-example/pom.xml +++ b/rocketmq-example/pom.xml @@ -1,14 +1,12 @@ - + com.alibaba.rocketmq rocketmq-all - 3.0.0-SNAPSHOT + 3.0.8-SNAPSHOT 4.0.0 jar - com.alibaba.rocketmq rocketmq-example rocketmq-example ${project.version} @@ -22,5 +20,13 @@ ${project.groupId} rocketmq-client + + ch.qos.logback + logback-classic + + + ch.qos.logback + logback-core + diff --git a/rocketmq-example/src/main/java/com/alibaba/rocketmq/example/README.md b/rocketmq-example/src/main/java/com/alibaba/rocketmq/example/README.md new file mode 100644 index 00000000..239460eb --- /dev/null +++ b/rocketmq-example/src/main/java/com/alibaba/rocketmq/example/README.md @@ -0,0 +1,7 @@ +### 发送非顺序消息 +### 发送顺序消息 +### 发送事务消息 +### 订阅非顺序消息 +### 订阅顺序消息 +### 主动Pull消息 +### 广播方式订阅消息 diff --git a/rocketmq-example/src/main/java/com/alibaba/rocketmq/example/benchmark/Consumer.java b/rocketmq-example/src/main/java/com/alibaba/rocketmq/example/benchmark/Consumer.java index 9b9a2d74..f51e7e46 100644 --- a/rocketmq-example/src/main/java/com/alibaba/rocketmq/example/benchmark/Consumer.java +++ b/rocketmq-example/src/main/java/com/alibaba/rocketmq/example/benchmark/Consumer.java @@ -1,16 +1,190 @@ /** - * $Id: Consumer.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.example.benchmark; +import java.util.LinkedList; +import java.util.List; +import java.util.Timer; +import java.util.TimerTask; +import java.util.concurrent.atomic.AtomicLong; + +import com.alibaba.rocketmq.client.consumer.DefaultMQPushConsumer; +import com.alibaba.rocketmq.client.consumer.listener.ConsumeConcurrentlyContext; +import com.alibaba.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus; +import com.alibaba.rocketmq.client.consumer.listener.MessageListenerConcurrently; +import com.alibaba.rocketmq.client.exception.MQClientException; +import com.alibaba.rocketmq.common.message.MessageExt; + + /** - * @author vintage.wang@gmail.com shijia.wxr@taobao.com - * + * 性能测试,订阅消息 */ public class Consumer { - public static void main(String[] args) { - // TODO Auto-generated method stub + public static void main(String[] args) throws MQClientException { + final StatsBenchmarkConsumer statsBenchmarkConsumer = new StatsBenchmarkConsumer(); + + final Timer timer = new Timer("BenchmarkTimerThread", true); + + final LinkedList snapshotList = new LinkedList(); + + timer.scheduleAtFixedRate(new TimerTask() { + @Override + public void run() { + snapshotList.addLast(statsBenchmarkConsumer.createSnapshot()); + if (snapshotList.size() > 10) { + snapshotList.removeFirst(); + } + } + }, 1000, 1000); + + timer.scheduleAtFixedRate(new TimerTask() { + private void printStats() { + if (snapshotList.size() >= 10) { + Long[] begin = snapshotList.getFirst(); + Long[] end = snapshotList.getLast(); + + final long consumeTps = + (long) (((end[1] - begin[1]) / (double) (end[0] - begin[0])) * 1000L); + final double averageB2CRT = ((end[2] - begin[2]) / (double) (end[1] - begin[1])); + final double averageS2CRT = ((end[3] - begin[3]) / (double) (end[1] - begin[1])); + + System.out.printf( + "Consume TPS: %d Average(B2C) RT: %7.3f Average(S2C) RT: %7.3f MAX(B2C) RT: %d MAX(S2C) RT: %d\n"// + , consumeTps// + , averageB2CRT// + , averageS2CRT// + , end[4]// + , end[5]// + ); + } + } + + + @Override + public void run() { + try { + this.printStats(); + } + catch (Exception e) { + e.printStackTrace(); + } + } + }, 10000, 10000); + + DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("benchmark_consumer"); + consumer.setInstanceName(Long.toString(System.currentTimeMillis())); + + consumer.subscribe("BenchmarkTest", "*"); + + consumer.registerMessageListener(new MessageListenerConcurrently() { + @Override + public ConsumeConcurrentlyStatus consumeMessage(List msgs, + ConsumeConcurrentlyContext context) { + MessageExt msg = msgs.get(0); + long now = System.currentTimeMillis(); + + // 1 + statsBenchmarkConsumer.getReceiveMessageTotalCount().incrementAndGet(); + + // 2 + long born2ConsumerRT = now - msg.getBornTimestamp(); + statsBenchmarkConsumer.getBorn2ConsumerTotalRT().addAndGet(born2ConsumerRT); + + // 3 + long store2ConsumerRT = now - msg.getStoreTimestamp(); + statsBenchmarkConsumer.getStore2ConsumerTotalRT().addAndGet(store2ConsumerRT); + + // 4 + compareAndSetMax(statsBenchmarkConsumer.getBorn2ConsumerMaxRT(), born2ConsumerRT); + + // 5 + compareAndSetMax(statsBenchmarkConsumer.getStore2ConsumerMaxRT(), store2ConsumerRT); + + return ConsumeConcurrentlyStatus.CONSUME_SUCCESS; + } + }); + + consumer.start(); + + System.out.println("Consumer Started."); + } + + + public static void compareAndSetMax(final AtomicLong target, final long value) { + long prev = target.get(); + while (value > prev) { + boolean updated = target.compareAndSet(prev, value); + if (updated) + break; + + prev = target.get(); + } + } +} + + +class StatsBenchmarkConsumer { + // 1 + private final AtomicLong receiveMessageTotalCount = new AtomicLong(0L); + // 2 + private final AtomicLong born2ConsumerTotalRT = new AtomicLong(0L); + // 3 + private final AtomicLong store2ConsumerTotalRT = new AtomicLong(0L); + // 4 + private final AtomicLong born2ConsumerMaxRT = new AtomicLong(0L); + // 5 + private final AtomicLong store2ConsumerMaxRT = new AtomicLong(0L); + + + public Long[] createSnapshot() { + Long[] snap = new Long[] {// + System.currentTimeMillis(),// + this.receiveMessageTotalCount.get(),// + this.born2ConsumerTotalRT.get(),// + this.store2ConsumerTotalRT.get(),// + this.born2ConsumerMaxRT.get(),// + this.store2ConsumerMaxRT.get(), // + }; + + return snap; + } + + + public AtomicLong getReceiveMessageTotalCount() { + return receiveMessageTotalCount; + } + + + public AtomicLong getBorn2ConsumerTotalRT() { + return born2ConsumerTotalRT; + } + + + public AtomicLong getStore2ConsumerTotalRT() { + return store2ConsumerTotalRT; + } + + + public AtomicLong getBorn2ConsumerMaxRT() { + return born2ConsumerMaxRT; + } + + public AtomicLong getStore2ConsumerMaxRT() { + return store2ConsumerMaxRT; } } diff --git a/rocketmq-example/src/main/java/com/alibaba/rocketmq/example/benchmark/Producer.java b/rocketmq-example/src/main/java/com/alibaba/rocketmq/example/benchmark/Producer.java index d8bc8db1..1ab344c1 100644 --- a/rocketmq-example/src/main/java/com/alibaba/rocketmq/example/benchmark/Producer.java +++ b/rocketmq-example/src/main/java/com/alibaba/rocketmq/example/benchmark/Producer.java @@ -1,5 +1,17 @@ /** - * $Id: Producer.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.example.benchmark; @@ -13,42 +25,25 @@ import com.alibaba.rocketmq.client.exception.MQBrokerException; import com.alibaba.rocketmq.client.exception.MQClientException; import com.alibaba.rocketmq.client.producer.DefaultMQProducer; -import com.alibaba.rocketmq.client.producer.SendResult; -import com.alibaba.rocketmq.common.Message; +import com.alibaba.rocketmq.common.message.Message; import com.alibaba.rocketmq.remoting.exception.RemotingException; /** - * ܲԣ߳ͬϢ - * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com - * + * 性能测试,多线程同步发送消息 */ public class Producer { - private static Message buildMessage(final int messageSize) { - Message msg = new Message(); - msg.setTopic("BenchmarkTest4"); - - StringBuilder sb = new StringBuilder(); - for (int i = 0; i < messageSize; i += 10) { - sb.append("hello baby"); - } - - msg.setBody(sb.toString().getBytes()); - - return msg; - } - - public static void main(String[] args) throws MQClientException { final int threadCount = args.length >= 1 ? Integer.parseInt(args[0]) : 32; - final int messageSize = args.length >= 2 ? Integer.parseInt(args[1]) : 1024 * 2; + final int messageSize = args.length >= 2 ? Integer.parseInt(args[1]) : 256; + + System.out.printf("threadCount %d messageSize %d\n", threadCount, messageSize); final Message msg = buildMessage(messageSize); final ExecutorService sendThreadPool = Executors.newFixedThreadPool(threadCount); - final StatsBenchmark statsBenchmark = new StatsBenchmark(); + final StatsBenchmarkProducer statsBenchmark = new StatsBenchmarkProducer(); final Timer timer = new Timer("BenchmarkTimerThread", true); @@ -70,7 +65,8 @@ private void printStats() { Long[] begin = snapshotList.getFirst(); Long[] end = snapshotList.getLast(); - final long sendTps = (long) (((end[3] - begin[3]) / (double) (end[0] - begin[0])) * 1000L); + final long sendTps = + (long) (((end[3] - begin[3]) / (double) (end[0] - begin[0])) * 1000L); final double averageRT = ((end[5] - begin[5]) / (double) (end[3] - begin[3])); System.out.printf( @@ -97,8 +93,9 @@ public void run() { }, 10000, 10000); final DefaultMQProducer producer = new DefaultMQProducer("benchmark_producer"); + producer.setInstanceName(Long.toString(System.currentTimeMillis())); - producer.setDefaultTopicQueueNums(1000); + producer.setCompressMsgBodyOverHowmuch(Integer.MAX_VALUE); producer.start(); @@ -108,9 +105,8 @@ public void run() { public void run() { while (true) { try { - // Thread.sleep(1000); final long beginTimestamp = System.currentTimeMillis(); - final SendResult sendResult = producer.send(msg); + producer.send(msg); statsBenchmark.getSendRequestSuccessCount().incrementAndGet(); statsBenchmark.getReceiveResponseSuccessCount().incrementAndGet(); final long currentRT = System.currentTimeMillis() - beginTimestamp; @@ -118,7 +114,8 @@ public void run() { long prevMaxRT = statsBenchmark.getSendMessageMaxRT().get(); while (currentRT > prevMaxRT) { boolean updated = - statsBenchmark.getSendMessageMaxRT().compareAndSet(prevMaxRT, currentRT); + statsBenchmark.getSendMessageMaxRT().compareAndSet(prevMaxRT, + currentRT); if (updated) break; @@ -146,10 +143,25 @@ public void run() { }); } } + + + private static Message buildMessage(final int messageSize) { + Message msg = new Message(); + msg.setTopic("BenchmarkTest"); + + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < messageSize; i += 10) { + sb.append("hello baby"); + } + + msg.setBody(sb.toString().getBytes()); + + return msg; + } } -class StatsBenchmark { +class StatsBenchmarkProducer { // 1 private final AtomicLong sendRequestSuccessCount = new AtomicLong(0L); // 2 diff --git a/rocketmq-example/src/main/java/com/alibaba/rocketmq/example/benchmark/TransactionProducer.java b/rocketmq-example/src/main/java/com/alibaba/rocketmq/example/benchmark/TransactionProducer.java new file mode 100644 index 00000000..7f5a2b42 --- /dev/null +++ b/rocketmq-example/src/main/java/com/alibaba/rocketmq/example/benchmark/TransactionProducer.java @@ -0,0 +1,278 @@ +/** + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.rocketmq.example.benchmark; + +import java.util.LinkedList; +import java.util.Timer; +import java.util.TimerTask; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.atomic.AtomicLong; + +import com.alibaba.rocketmq.client.exception.MQClientException; +import com.alibaba.rocketmq.client.producer.LocalTransactionExecuter; +import com.alibaba.rocketmq.client.producer.LocalTransactionState; +import com.alibaba.rocketmq.client.producer.SendResult; +import com.alibaba.rocketmq.client.producer.TransactionCheckListener; +import com.alibaba.rocketmq.client.producer.TransactionMQProducer; +import com.alibaba.rocketmq.common.message.Message; +import com.alibaba.rocketmq.common.message.MessageExt; + + +/** + * 性能测试,多线程同步发送事务消息 + */ +public class TransactionProducer { + private static int threadCount; + private static int messageSize; + private static boolean ischeck; + private static boolean ischeckffalse; + + + public static void main(String[] args) throws MQClientException { + threadCount = args.length >= 1 ? Integer.parseInt(args[0]) : 32; + messageSize = args.length >= 2 ? Integer.parseInt(args[1]) : 1024 * 2; + ischeck = args.length >= 3 ? Boolean.parseBoolean(args[2]) : false; + ischeckffalse = args.length >= 4 ? Boolean.parseBoolean(args[3]) : false; + + final Message msg = buildMessage(messageSize); + + final ExecutorService sendThreadPool = Executors.newFixedThreadPool(threadCount); + + final StatsBenchmarkTProducer statsBenchmark = new StatsBenchmarkTProducer(); + + final Timer timer = new Timer("BenchmarkTimerThread", true); + + final LinkedList snapshotList = new LinkedList(); + + timer.scheduleAtFixedRate(new TimerTask() { + @Override + public void run() { + snapshotList.addLast(statsBenchmark.createSnapshot()); + while (snapshotList.size() > 10) { + snapshotList.removeFirst(); + } + } + }, 1000, 1000); + + timer.scheduleAtFixedRate(new TimerTask() { + private void printStats() { + if (snapshotList.size() >= 10) { + Long[] begin = snapshotList.getFirst(); + Long[] end = snapshotList.getLast(); + + final long sendTps = + (long) (((end[3] - begin[3]) / (double) (end[0] - begin[0])) * 1000L); + final double averageRT = ((end[5] - begin[5]) / (double) (end[3] - begin[3])); + + System.out.printf( + "Send TPS: %d Max RT: %d Average RT: %7.3f Send Failed: %d Response Failed: %d transaction checkCount: %d \n"// + , sendTps// + , statsBenchmark.getSendMessageMaxRT().get()// + , averageRT// + , end[2]// + , end[4]// + , end[6]); + } + } + + + @Override + public void run() { + try { + this.printStats(); + } + catch (Exception e) { + e.printStackTrace(); + } + } + }, 10000, 10000); + + final TransactionCheckListener transactionCheckListener = + new TransactionCheckListenerBImpl(ischeckffalse, statsBenchmark); + final TransactionMQProducer producer = new TransactionMQProducer("benchmark_transaction_producer"); + producer.setInstanceName(Long.toString(System.currentTimeMillis())); + producer.setTransactionCheckListener(transactionCheckListener); + producer.setDefaultTopicQueueNums(1000); + producer.start(); + + final TransactionExecuterBImpl tranExecuter = new TransactionExecuterBImpl(ischeck); + + for (int i = 0; i < threadCount; i++) { + sendThreadPool.execute(new Runnable() { + @Override + public void run() { + while (true) { + try { + // Thread.sleep(1000); + final long beginTimestamp = System.currentTimeMillis(); + SendResult sendResult = + producer.sendMessageInTransaction(msg, tranExecuter, null); + if (sendResult != null) { + statsBenchmark.getSendRequestSuccessCount().incrementAndGet(); + statsBenchmark.getReceiveResponseSuccessCount().incrementAndGet(); + } + + final long currentRT = System.currentTimeMillis() - beginTimestamp; + statsBenchmark.getSendMessageSuccessTimeTotal().addAndGet(currentRT); + long prevMaxRT = statsBenchmark.getSendMessageMaxRT().get(); + while (currentRT > prevMaxRT) { + boolean updated = + statsBenchmark.getSendMessageMaxRT().compareAndSet(prevMaxRT, + currentRT); + if (updated) + break; + + prevMaxRT = statsBenchmark.getSendMessageMaxRT().get(); + } + } + catch (MQClientException e) { + statsBenchmark.getSendRequestFailedCount().incrementAndGet(); + } + } + } + }); + } + } + + + private static Message buildMessage(final int messageSize) { + Message msg = new Message(); + msg.setTopic("BenchmarkTest"); + + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < messageSize; i += 10) { + sb.append("hello baby"); + } + + msg.setBody(sb.toString().getBytes()); + + return msg; + } +} + + +class TransactionExecuterBImpl implements LocalTransactionExecuter { + + private boolean ischeck; + + + public TransactionExecuterBImpl(boolean ischeck) { + this.ischeck = ischeck; + } + + + @Override + public LocalTransactionState executeLocalTransactionBranch(final Message msg, final Object arg) { + if (ischeck) { + return LocalTransactionState.UNKNOW; + } + return LocalTransactionState.COMMIT_MESSAGE; + } +} + + +class TransactionCheckListenerBImpl implements TransactionCheckListener { + private boolean ischeckffalse; + private StatsBenchmarkTProducer statsBenchmarkTProducer; + + + public TransactionCheckListenerBImpl(boolean ischeckffalse, + StatsBenchmarkTProducer statsBenchmarkTProducer) { + this.ischeckffalse = ischeckffalse; + this.statsBenchmarkTProducer = statsBenchmarkTProducer; + } + + + @Override + public LocalTransactionState checkLocalTransactionState(MessageExt msg) { + // System.out.println("server checking TrMsg " + msg.toString()); + statsBenchmarkTProducer.getCheckRequestSuccessCount().incrementAndGet(); + if (ischeckffalse) { + + return LocalTransactionState.ROLLBACK_MESSAGE; + } + + return LocalTransactionState.COMMIT_MESSAGE; + } +} + + +class StatsBenchmarkTProducer { + // 1 + private final AtomicLong sendRequestSuccessCount = new AtomicLong(0L); + // 2 + private final AtomicLong sendRequestFailedCount = new AtomicLong(0L); + // 3 + private final AtomicLong receiveResponseSuccessCount = new AtomicLong(0L); + // 4 + private final AtomicLong receiveResponseFailedCount = new AtomicLong(0L); + // 5 + private final AtomicLong sendMessageSuccessTimeTotal = new AtomicLong(0L); + // 6 + private final AtomicLong sendMessageMaxRT = new AtomicLong(0L); + // 7 + private final AtomicLong checkRequestSuccessCount = new AtomicLong(0L); + + + public Long[] createSnapshot() { + Long[] snap = new Long[] {// + System.currentTimeMillis(),// + this.sendRequestSuccessCount.get(),// + this.sendRequestFailedCount.get(),// + this.receiveResponseSuccessCount.get(),// + this.receiveResponseFailedCount.get(),// + this.sendMessageSuccessTimeTotal.get(), // + this.checkRequestSuccessCount.get(), }; + + return snap; + } + + + public AtomicLong getSendRequestSuccessCount() { + return sendRequestSuccessCount; + } + + + public AtomicLong getSendRequestFailedCount() { + return sendRequestFailedCount; + } + + + public AtomicLong getReceiveResponseSuccessCount() { + return receiveResponseSuccessCount; + } + + + public AtomicLong getReceiveResponseFailedCount() { + return receiveResponseFailedCount; + } + + + public AtomicLong getSendMessageSuccessTimeTotal() { + return sendMessageSuccessTimeTotal; + } + + + public AtomicLong getSendMessageMaxRT() { + return sendMessageMaxRT; + } + + + public AtomicLong getCheckRequestSuccessCount() { + return checkRequestSuccessCount; + } +} diff --git a/rocketmq-example/src/main/java/com/alibaba/rocketmq/example/broadcast/PushConsumer.java b/rocketmq-example/src/main/java/com/alibaba/rocketmq/example/broadcast/PushConsumer.java new file mode 100644 index 00000000..e4daa551 --- /dev/null +++ b/rocketmq-example/src/main/java/com/alibaba/rocketmq/example/broadcast/PushConsumer.java @@ -0,0 +1,57 @@ +/** + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.rocketmq.example.broadcast; + +import java.util.List; + +import com.alibaba.rocketmq.client.consumer.DefaultMQPushConsumer; +import com.alibaba.rocketmq.client.consumer.listener.ConsumeConcurrentlyContext; +import com.alibaba.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus; +import com.alibaba.rocketmq.client.consumer.listener.MessageListenerConcurrently; +import com.alibaba.rocketmq.client.exception.MQClientException; +import com.alibaba.rocketmq.common.message.MessageExt; +import com.alibaba.rocketmq.common.protocol.heartbeat.MessageModel; + + +/** + * PushConsumer,广播方式订阅消息 + * + */ +public class PushConsumer { + + public static void main(String[] args) throws InterruptedException, MQClientException { + DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("please_rename_unique_group_name_1"); + + consumer.setMessageModel(MessageModel.BROADCASTING); + + consumer.subscribe("TopicTest", "TagA || TagC || TagD"); + + consumer.registerMessageListener(new MessageListenerConcurrently() { + + @Override + public ConsumeConcurrentlyStatus consumeMessage(List msgs, + ConsumeConcurrentlyContext context) { + System.out.println(Thread.currentThread().getName() + " Receive New Messages: " + msgs); + + return ConsumeConcurrentlyStatus.CONSUME_SUCCESS; + } + }); + + consumer.start(); + + System.out.println("Broadcast Consumer Started."); + } +} diff --git a/rocketmq-example/src/main/java/com/alibaba/rocketmq/example/operation/Consumer.java b/rocketmq-example/src/main/java/com/alibaba/rocketmq/example/operation/Consumer.java new file mode 100644 index 00000000..b2df8d1b --- /dev/null +++ b/rocketmq-example/src/main/java/com/alibaba/rocketmq/example/operation/Consumer.java @@ -0,0 +1,122 @@ +/** + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.rocketmq.example.operation; + +import java.util.List; +import java.util.concurrent.atomic.AtomicLong; + +import org.apache.commons.cli.CommandLine; +import org.apache.commons.cli.HelpFormatter; +import org.apache.commons.cli.Option; +import org.apache.commons.cli.Options; +import org.apache.commons.cli.ParseException; +import org.apache.commons.cli.PosixParser; + +import com.alibaba.rocketmq.client.consumer.DefaultMQPushConsumer; +import com.alibaba.rocketmq.client.consumer.listener.ConsumeConcurrentlyContext; +import com.alibaba.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus; +import com.alibaba.rocketmq.client.consumer.listener.MessageListenerConcurrently; +import com.alibaba.rocketmq.client.exception.MQClientException; +import com.alibaba.rocketmq.common.message.MessageExt; + + +public class Consumer { + + public static CommandLine buildCommandline(String[] args) { + final Options options = new Options(); + // //////////////////////////////////////////////////// + Option opt = new Option("h", "help", false, "Print help"); + opt.setRequired(false); + options.addOption(opt); + + opt = new Option("g", "consumerGroup", true, "Consumer Group Name"); + opt.setRequired(true); + options.addOption(opt); + + opt = new Option("t", "topic", true, "Topic Name"); + opt.setRequired(true); + options.addOption(opt); + + opt = new Option("s", "subscription", true, "subscription"); + opt.setRequired(false); + options.addOption(opt); + + opt = new Option("f", "returnFailedHalf", true, "return failed result, for half message"); + opt.setRequired(true); + options.addOption(opt); + + // //////////////////////////////////////////////////// + + PosixParser parser = new PosixParser(); + HelpFormatter hf = new HelpFormatter(); + hf.setWidth(110); + CommandLine commandLine = null; + try { + commandLine = parser.parse(options, args); + if (commandLine.hasOption('h')) { + hf.printHelp("producer", options, true); + return null; + } + } + catch (ParseException e) { + hf.printHelp("producer", options, true); + return null; + } + + return commandLine; + } + + + public static void main(String[] args) throws InterruptedException, MQClientException { + CommandLine commandLine = buildCommandline(args); + if (commandLine != null) { + String group = commandLine.getOptionValue('g'); + String topic = commandLine.getOptionValue('t'); + String subscription = commandLine.getOptionValue('s'); + final String returnFailedHalf = commandLine.getOptionValue('f'); + + DefaultMQPushConsumer consumer = new DefaultMQPushConsumer(group); + consumer.setInstanceName(Long.toString(System.currentTimeMillis())); + + consumer.subscribe(topic, subscription); + + consumer.registerMessageListener(new MessageListenerConcurrently() { + AtomicLong consumeTimes = new AtomicLong(0); + + + @Override + public ConsumeConcurrentlyStatus consumeMessage(List msgs, + ConsumeConcurrentlyContext context) { + long currentTimes = this.consumeTimes.incrementAndGet(); + + System.out.printf("%-8d %s\n", currentTimes, msgs); + + if (Boolean.parseBoolean(returnFailedHalf)) { + if ((currentTimes % 2) == 0) { + return ConsumeConcurrentlyStatus.RECONSUME_LATER; + } + } + + return ConsumeConcurrentlyStatus.CONSUME_SUCCESS; + } + }); + + consumer.start(); + + System.out.println("Consumer Started."); + } + } +} diff --git a/rocketmq-example/src/main/java/com/alibaba/rocketmq/example/operation/Producer.java b/rocketmq-example/src/main/java/com/alibaba/rocketmq/example/operation/Producer.java new file mode 100644 index 00000000..1f69f91d --- /dev/null +++ b/rocketmq-example/src/main/java/com/alibaba/rocketmq/example/operation/Producer.java @@ -0,0 +1,119 @@ +/** + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.rocketmq.example.operation; + +import org.apache.commons.cli.CommandLine; +import org.apache.commons.cli.HelpFormatter; +import org.apache.commons.cli.Option; +import org.apache.commons.cli.Options; +import org.apache.commons.cli.ParseException; +import org.apache.commons.cli.PosixParser; + +import com.alibaba.rocketmq.client.exception.MQClientException; +import com.alibaba.rocketmq.client.producer.DefaultMQProducer; +import com.alibaba.rocketmq.client.producer.SendResult; +import com.alibaba.rocketmq.common.message.Message; + + +/** + * Producer,发送消息,内置到安装包,方便线上进行调试定位问题 + */ +public class Producer { + + public static CommandLine buildCommandline(String[] args) { + final Options options = new Options(); + // //////////////////////////////////////////////////// + Option opt = new Option("h", "help", false, "Print help"); + opt.setRequired(false); + options.addOption(opt); + + opt = new Option("g", "producerGroup", true, "Producer Group Name"); + opt.setRequired(true); + options.addOption(opt); + + opt = new Option("t", "topic", true, "Topic Name"); + opt.setRequired(true); + options.addOption(opt); + + opt = new Option("a", "tags", true, "Tags Name"); + opt.setRequired(true); + options.addOption(opt); + + opt = new Option("k", "keys", true, "Keys Name"); + opt.setRequired(true); + options.addOption(opt); + + opt = new Option("c", "msgCount", true, "Message Count"); + opt.setRequired(true); + options.addOption(opt); + + // //////////////////////////////////////////////////// + + PosixParser parser = new PosixParser(); + HelpFormatter hf = new HelpFormatter(); + hf.setWidth(110); + CommandLine commandLine = null; + try { + commandLine = parser.parse(options, args); + if (commandLine.hasOption('h')) { + hf.printHelp("producer", options, true); + return null; + } + } + catch (ParseException e) { + hf.printHelp("producer", options, true); + return null; + } + + return commandLine; + } + + + public static void main(String[] args) throws MQClientException, InterruptedException { + CommandLine commandLine = buildCommandline(args); + if (commandLine != null) { + String group = commandLine.getOptionValue('g'); + String topic = commandLine.getOptionValue('t'); + String tags = commandLine.getOptionValue('a'); + String keys = commandLine.getOptionValue('k'); + String msgCount = commandLine.getOptionValue('c'); + + DefaultMQProducer producer = new DefaultMQProducer(group); + producer.setInstanceName(Long.toString(System.currentTimeMillis())); + + producer.start(); + + for (int i = 0; i < Integer.parseInt(msgCount); i++) { + try { + Message msg = new Message(// + topic,// topic + tags,// tag + keys,// key + ("Hello RocketMQ " + i).getBytes());// body + SendResult sendResult = producer.send(msg); + + System.out.printf("%-8d %s\n", i, sendResult); + } + catch (Exception e) { + e.printStackTrace(); + Thread.sleep(1000); + } + } + + producer.shutdown(); + } + } +} diff --git a/rocketmq-example/src/main/java/com/alibaba/rocketmq/example/ordermessage/Consumer.java b/rocketmq-example/src/main/java/com/alibaba/rocketmq/example/ordermessage/Consumer.java new file mode 100644 index 00000000..0b415507 --- /dev/null +++ b/rocketmq-example/src/main/java/com/alibaba/rocketmq/example/ordermessage/Consumer.java @@ -0,0 +1,71 @@ +/** + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.rocketmq.example.ordermessage; + +import java.util.List; +import java.util.concurrent.atomic.AtomicLong; + +import com.alibaba.rocketmq.client.consumer.DefaultMQPushConsumer; +import com.alibaba.rocketmq.client.consumer.listener.ConsumeOrderlyContext; +import com.alibaba.rocketmq.client.consumer.listener.ConsumeOrderlyStatus; +import com.alibaba.rocketmq.client.consumer.listener.MessageListenerOrderly; +import com.alibaba.rocketmq.client.exception.MQClientException; +import com.alibaba.rocketmq.common.message.MessageExt; + + +/** + * 顺序消息消费,带事务方式(应用可控制Offset什么时候提交) + */ +public class Consumer { + + public static void main(String[] args) throws MQClientException { + DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("please_rename_unique_group_name_3"); + + consumer.subscribe("TopicTest", "TagA || TagC || TagD"); + + consumer.registerMessageListener(new MessageListenerOrderly() { + AtomicLong consumeTimes = new AtomicLong(0); + + + @Override + public ConsumeOrderlyStatus consumeMessage(List msgs, ConsumeOrderlyContext context) { + context.setAutoCommit(false); + System.out.println(Thread.currentThread().getName() + " Receive New Messages: " + msgs); + this.consumeTimes.incrementAndGet(); + if ((this.consumeTimes.get() % 2) == 0) { + return ConsumeOrderlyStatus.SUCCESS; + } + else if ((this.consumeTimes.get() % 3) == 0) { + return ConsumeOrderlyStatus.ROLLBACK; + } + else if ((this.consumeTimes.get() % 4) == 0) { + return ConsumeOrderlyStatus.COMMIT; + } + else if ((this.consumeTimes.get() % 5) == 0) { + context.setSuspendCurrentQueueTimeMillis(3000); + return ConsumeOrderlyStatus.SUSPEND_CURRENT_QUEUE_A_MOMENT; + } + + return ConsumeOrderlyStatus.SUCCESS; + } + }); + + consumer.start(); + + System.out.println("Consumer Started."); + } + +} diff --git a/rocketmq-example/src/main/java/com/alibaba/rocketmq/example/ordermessage/Producer.java b/rocketmq-example/src/main/java/com/alibaba/rocketmq/example/ordermessage/Producer.java new file mode 100644 index 00000000..c2e7c55e --- /dev/null +++ b/rocketmq-example/src/main/java/com/alibaba/rocketmq/example/ordermessage/Producer.java @@ -0,0 +1,77 @@ +/** + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.rocketmq.example.ordermessage; + +import java.util.List; + +import com.alibaba.rocketmq.client.exception.MQBrokerException; +import com.alibaba.rocketmq.client.exception.MQClientException; +import com.alibaba.rocketmq.client.producer.DefaultMQProducer; +import com.alibaba.rocketmq.client.producer.MQProducer; +import com.alibaba.rocketmq.client.producer.MessageQueueSelector; +import com.alibaba.rocketmq.client.producer.SendResult; +import com.alibaba.rocketmq.common.message.Message; +import com.alibaba.rocketmq.common.message.MessageQueue; +import com.alibaba.rocketmq.remoting.exception.RemotingException; + + +/** + * Producer,发送顺序消息 + */ +public class Producer { + public static void main(String[] args) { + try { + MQProducer producer = new DefaultMQProducer("please_rename_unique_group_name"); + + producer.start(); + + String[] tags = new String[] { "TagA", "TagB", "TagC", "TagD", "TagE" }; + + for (int i = 0; i < 100; i++) { + // 订单ID相同的消息要有序 + int orderId = i % 10; + Message msg = + new Message("TopicTestjjj", tags[i % tags.length], "KEY" + i, + ("Hello RocketMQ " + i).getBytes()); + + SendResult sendResult = producer.send(msg, new MessageQueueSelector() { + @Override + public MessageQueue select(List mqs, Message msg, Object arg) { + Integer id = (Integer) arg; + int index = id % mqs.size(); + return mqs.get(index); + } + }, orderId); + + System.out.println(sendResult); + } + + producer.shutdown(); + } + catch (MQClientException e) { + e.printStackTrace(); + } + catch (RemotingException e) { + e.printStackTrace(); + } + catch (MQBrokerException e) { + e.printStackTrace(); + } + catch (InterruptedException e) { + e.printStackTrace(); + } + } +} diff --git a/rocketmq-example/src/main/java/com/alibaba/rocketmq/example/quickstart/Consumer.java b/rocketmq-example/src/main/java/com/alibaba/rocketmq/example/quickstart/Consumer.java new file mode 100644 index 00000000..a264f2f5 --- /dev/null +++ b/rocketmq-example/src/main/java/com/alibaba/rocketmq/example/quickstart/Consumer.java @@ -0,0 +1,52 @@ +/** + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.rocketmq.example.quickstart; + +import java.util.List; + +import com.alibaba.rocketmq.client.consumer.DefaultMQPushConsumer; +import com.alibaba.rocketmq.client.consumer.listener.ConsumeConcurrentlyContext; +import com.alibaba.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus; +import com.alibaba.rocketmq.client.consumer.listener.MessageListenerConcurrently; +import com.alibaba.rocketmq.client.exception.MQClientException; +import com.alibaba.rocketmq.common.message.MessageExt; + + +/** + * Consumer,订阅消息 + */ +public class Consumer { + + public static void main(String[] args) throws InterruptedException, MQClientException { + DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("please_rename_unique_group_name_4"); + + consumer.subscribe("TopicTest", "*"); + + consumer.registerMessageListener(new MessageListenerConcurrently() { + + @Override + public ConsumeConcurrentlyStatus consumeMessage(List msgs, + ConsumeConcurrentlyContext context) { + System.out.println(Thread.currentThread().getName() + " Receive New Messages: " + msgs); + return ConsumeConcurrentlyStatus.CONSUME_SUCCESS; + } + }); + + consumer.start(); + + System.out.println("Consumer Started."); + } +} diff --git a/rocketmq-example/src/main/java/com/alibaba/rocketmq/example/quickstart/Producer.java b/rocketmq-example/src/main/java/com/alibaba/rocketmq/example/quickstart/Producer.java new file mode 100644 index 00000000..a6e05b30 --- /dev/null +++ b/rocketmq-example/src/main/java/com/alibaba/rocketmq/example/quickstart/Producer.java @@ -0,0 +1,51 @@ +/** + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.rocketmq.example.quickstart; + +import com.alibaba.rocketmq.client.exception.MQClientException; +import com.alibaba.rocketmq.client.producer.DefaultMQProducer; +import com.alibaba.rocketmq.client.producer.SendResult; +import com.alibaba.rocketmq.common.message.Message; + + +/** + * Producer,发送消息 + * + */ +public class Producer { + public static void main(String[] args) throws MQClientException, InterruptedException { + DefaultMQProducer producer = new DefaultMQProducer("please_rename_unique_group_name"); + + producer.start(); + + for (int i = 0; i < 1000; i++) { + try { + Message msg = new Message("TopicTest",// topic + "TagA",// tag + ("Hello RocketMQ " + i).getBytes()// body + ); + SendResult sendResult = producer.send(msg); + System.out.println(sendResult); + } + catch (Exception e) { + e.printStackTrace(); + Thread.sleep(1000); + } + } + + producer.shutdown(); + } +} diff --git a/rocketmq-example/src/main/java/com/alibaba/rocketmq/example/simple/Producer.java b/rocketmq-example/src/main/java/com/alibaba/rocketmq/example/simple/Producer.java index d357e2a7..3db97986 100644 --- a/rocketmq-example/src/main/java/com/alibaba/rocketmq/example/simple/Producer.java +++ b/rocketmq-example/src/main/java/com/alibaba/rocketmq/example/simple/Producer.java @@ -1,50 +1,84 @@ /** - * $Id: Producer.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.example.simple; -import com.alibaba.rocketmq.client.exception.MQBrokerException; import com.alibaba.rocketmq.client.exception.MQClientException; import com.alibaba.rocketmq.client.producer.DefaultMQProducer; -import com.alibaba.rocketmq.client.producer.MQProducer; import com.alibaba.rocketmq.client.producer.SendResult; -import com.alibaba.rocketmq.common.Message; -import com.alibaba.rocketmq.remoting.exception.RemotingException; +import com.alibaba.rocketmq.common.message.Message; -/** - * @author vintage.wang@gmail.com shijia.wxr@taobao.com - * - */ public class Producer { - public static void main(String[] args) { - try { - MQProducer producer = new DefaultMQProducer("example.producer"); + public static void main(String[] args) throws MQClientException, InterruptedException { + /** + * 一个应用创建一个Producer,由应用来维护此对象,可以设置为全局对象或者单例
+ * 注意:ProducerGroupName需要由应用来保证唯一
+ * ProducerGroup这个概念发送普通的消息时,作用不大,但是发送分布式事务消息时,比较关键, + * 因为服务器会回查这个Group下的任意一个Producer + */ + DefaultMQProducer producer = new DefaultMQProducer("ProducerGroupName"); - producer.start(); + /** + * Producer对象在使用之前必须要调用start初始化,初始化一次即可
+ * 注意:切记不可以在每次发送消息时,都调用start方法 + */ + producer.start(); - String[] tags = new String[] { "TagA", "TagB", "TagC", "TagD", "TagE" }; + /** + * 下面这段代码表明一个Producer对象可以发送多个topic,多个tag的消息。 + * 注意:send方法是同步调用,只要不抛异常就标识成功。但是发送成功也可会有多种状态,
+ * 例如消息写入Master成功,但是Slave不成功,这种情况消息属于成功,但是对于个别应用如果对消息可靠性要求极高,
+ * 需要对这种情况做处理。另外,消息可能会存在发送失败的情况,失败重试由应用来处理。 + */ + try { + { + Message msg = new Message("TopicTest1",// topic + "TagA",// tag + "OrderID001",// key + ("Hello MetaQ").getBytes());// body + SendResult sendResult = producer.send(msg); + System.out.println(sendResult); + } - for (int i = 0; i < 100; i++) { - Message msg = - new Message("TopicTest", tags[i % tags.length], "KEY" + i, ("Hello RocketMQ " + i).getBytes()); + { + Message msg = new Message("TopicTest2",// topic + "TagB",// tag + "OrderID0034",// key + ("Hello MetaQ").getBytes());// body SendResult sendResult = producer.send(msg); System.out.println(sendResult); } - producer.shutdown(); - } - catch (MQClientException e) { - e.printStackTrace(); - } - catch (RemotingException e) { - e.printStackTrace(); - } - catch (MQBrokerException e) { - e.printStackTrace(); + { + Message msg = new Message("TopicTest3",// topic + "TagC",// tag + "OrderID061",// key + ("Hello MetaQ").getBytes());// body + SendResult sendResult = producer.send(msg); + System.out.println(sendResult); + } } - catch (InterruptedException e) { + catch (Exception e) { e.printStackTrace(); } + + /** + * 应用退出时,要调用shutdown来清理资源,关闭网络连接,从MetaQ服务器上注销自己 + * 注意:我们建议应用在JBOSS、Tomcat等容器的退出钩子里调用shutdown方法 + */ + producer.shutdown(); } } diff --git a/rocketmq-example/src/main/java/com/alibaba/rocketmq/example/simple/PullConsumer.java b/rocketmq-example/src/main/java/com/alibaba/rocketmq/example/simple/PullConsumer.java index d06a02b9..976e0cb6 100644 --- a/rocketmq-example/src/main/java/com/alibaba/rocketmq/example/simple/PullConsumer.java +++ b/rocketmq-example/src/main/java/com/alibaba/rocketmq/example/simple/PullConsumer.java @@ -1,37 +1,72 @@ /** - * $Id: PullConsumer.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.example.simple; import java.util.HashMap; -import java.util.List; import java.util.Map; +import java.util.Set; import com.alibaba.rocketmq.client.consumer.DefaultMQPullConsumer; -import com.alibaba.rocketmq.client.consumer.MQPullConsumer; import com.alibaba.rocketmq.client.consumer.PullResult; -import com.alibaba.rocketmq.client.exception.MQBrokerException; import com.alibaba.rocketmq.client.exception.MQClientException; -import com.alibaba.rocketmq.common.MessageQueue; -import com.alibaba.rocketmq.remoting.exception.RemotingException; +import com.alibaba.rocketmq.common.message.MessageQueue; /** - * ϢʽConsumer - * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com - * + * PullConsumer,订阅消息 */ public class PullConsumer { - private static Map offseTable = new HashMap(); + private static final Map offseTable = new HashMap(); - private static long getMessageQueueOffset(MessageQueue mq) { - Long offset = offseTable.get(mq); - if (offset != null) - return offset; + public static void main(String[] args) throws MQClientException { + DefaultMQPullConsumer consumer = new DefaultMQPullConsumer("please_rename_unique_group_name_5"); - return 0; + consumer.start(); + + Set mqs = consumer.fetchSubscribeMessageQueues("TopicTest"); + for (MessageQueue mq : mqs) { + System.out.println("Consume from the queue: " + mq); + SINGLE_MQ: while (true) { + try { + PullResult pullResult = + consumer.pullBlockIfNotFound(mq, null, getMessageQueueOffset(mq), 32); + System.out.println(pullResult); + putMessageQueueOffset(mq, pullResult.getNextBeginOffset()); + switch (pullResult.getPullStatus()) { + case FOUND: + // TODO + break; + case NO_MATCHED_MSG: + break; + case NO_NEW_MSG: + break SINGLE_MQ; + case OFFSET_ILLEGAL: + break; + default: + break; + } + } + catch (Exception e) { + e.printStackTrace(); + } + } + } + + consumer.shutdown(); } @@ -40,46 +75,12 @@ private static void putMessageQueueOffset(MessageQueue mq, long offset) { } - public static void main(String[] args) { - try { - MQPullConsumer consumer = new DefaultMQPullConsumer("example.consumer.active"); - - consumer.start(); - - List mqs = consumer.fetchSubscribeMessageQueues("TopicTest"); - for (MessageQueue mq : mqs) { - System.out.println("Consume from the queue: " + mq); - PullResult pullResult = consumer.pullBlockIfNotFound(mq, null, getMessageQueueOffset(mq), 32); - System.out.println(pullResult); - switch (pullResult.getPullStatus()) { - case FOUND: - break; - case NO_MATCHED_MSG: - break; - case NO_NEW_MSG: - break; - case OFFSET_ILLEGAL: - break; - default: - break; - } - - putMessageQueueOffset(mq, pullResult.getNextBeginOffset()); - } + private static long getMessageQueueOffset(MessageQueue mq) { + Long offset = offseTable.get(mq); + if (offset != null) + return offset; - consumer.shutdown(); - } - catch (MQClientException e) { - e.printStackTrace(); - } - catch (RemotingException e) { - e.printStackTrace(); - } - catch (MQBrokerException e) { - e.printStackTrace(); - } - catch (InterruptedException e) { - e.printStackTrace(); - } + return 0; } + } diff --git a/rocketmq-example/src/main/java/com/alibaba/rocketmq/example/simple/PushConsumer.java b/rocketmq-example/src/main/java/com/alibaba/rocketmq/example/simple/PushConsumer.java index 340a0d20..42713077 100644 --- a/rocketmq-example/src/main/java/com/alibaba/rocketmq/example/simple/PushConsumer.java +++ b/rocketmq-example/src/main/java/com/alibaba/rocketmq/example/simple/PushConsumer.java @@ -1,56 +1,89 @@ /** - * $Id: PushConsumer.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.example.simple; import java.util.List; -import java.util.concurrent.atomic.AtomicLong; import com.alibaba.rocketmq.client.consumer.DefaultMQPushConsumer; -import com.alibaba.rocketmq.client.consumer.MQPushConsumer; import com.alibaba.rocketmq.client.consumer.listener.ConsumeConcurrentlyContext; import com.alibaba.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus; import com.alibaba.rocketmq.client.consumer.listener.MessageListenerConcurrently; -import com.alibaba.rocketmq.common.MessageExt; +import com.alibaba.rocketmq.client.exception.MQClientException; +import com.alibaba.rocketmq.common.message.MessageExt; -/** - * Broker PushϢConsumer - * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com - * - */ public class PushConsumer { - public static void main(String[] args) throws InterruptedException { - MQPushConsumer consumer = new DefaultMQPushConsumer("example.consumer.passive"); + /** + * 当前例子是PushConsumer用法,使用方式给用户感觉是消息从RocketMQ服务器推到了应用客户端。
+ * 但是实际PushConsumer内部是使用长轮询Pull方式从MetaQ服务器拉消息,然后再回调用户Listener方法
+ */ + public static void main(String[] args) throws InterruptedException, MQClientException { + /** + * 一个应用创建一个Consumer,由应用来维护此对象,可以设置为全局对象或者单例
+ * 注意:ConsumerGroupName需要由应用来保证唯一 + */ + DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("ConsumerGroupName"); - consumer.subscribe("TopicTest", "TagA || TagC || TagD"); + /** + * 订阅指定topic下tags分别等于TagA或TagC或TagD + */ + consumer.subscribe("TopicTest1", "TagA || TagC || TagD"); + /** + * 订阅指定topic下所有消息
+ * 注意:一个consumer对象可以订阅多个topic + */ + consumer.subscribe("TopicTest2", "*"); consumer.registerMessageListener(new MessageListenerConcurrently() { - AtomicLong consumeTimes = new AtomicLong(0); - + /** + * 默认msgs里只有一条消息,可以通过设置consumeMessageBatchMaxSize参数来批量接收消息 + */ @Override public ConsumeConcurrentlyStatus consumeMessage(List msgs, ConsumeConcurrentlyContext context) { - System.out.println("Receive New Messages: " + msgs); - // ģʧ - if ((this.consumeTimes.getAndIncrement() % 5) == 0) { - return ConsumeConcurrentlyStatus.RECONSUME_LATER; + System.out.println(Thread.currentThread().getName() + " Receive New Messages: " + msgs); + + MessageExt msg = msgs.get(0); + if (msg.getTopic().equals("TopicTest1")) { + // 执行TopicTest1的消费逻辑 + if (msg.getTags() != null && msg.getTags().equals("TagA")) { + // 执行TagA的消费 + } + else if (msg.getTags() != null && msg.getTags().equals("TagC")) { + // 执行TagC的消费 + } + else if (msg.getTags() != null && msg.getTags().equals("TagD")) { + // 执行TagD的消费 + } + } + else if (msg.getTopic().equals("TopicTest2")) { + // 执行TopicTest2的消费逻辑 } return ConsumeConcurrentlyStatus.CONSUME_SUCCESS; } }); + /** + * Consumer对象在使用之前必须要调用start初始化,初始化一次即可
+ */ consumer.start(); System.out.println("Consumer Started."); - - while (true) { - Thread.sleep(1000); - } } - } diff --git a/rocketmq-example/src/main/java/com/alibaba/rocketmq/example/transaction/TranExecuterImpl.java b/rocketmq-example/src/main/java/com/alibaba/rocketmq/example/transaction/TranExecuterImpl.java deleted file mode 100644 index b952ac7b..00000000 --- a/rocketmq-example/src/main/java/com/alibaba/rocketmq/example/transaction/TranExecuterImpl.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.alibaba.rocketmq.example.transaction; - -import com.alibaba.rocketmq.client.producer.LocalTransactionExecuter; -import com.alibaba.rocketmq.client.producer.LocalTransactionState; -import com.alibaba.rocketmq.common.Message; - - -public class TranExecuterImpl implements LocalTransactionExecuter { - private int transactionStats = -1;// 0 send ,1 commit,2 rollback - - - public int getTransactionStats() { - return transactionStats; - } - - - public void setTransactionStats(int transactionStats) { - this.transactionStats = transactionStats; - } - - - @Override - public LocalTransactionState executeLocalTransactionBranch(Message msg) { - if (transactionStats == 1) { - return LocalTransactionState.COMMIT_MESSAGE; - } - else if (transactionStats == 2) { - return LocalTransactionState.ROLLBACK_MESSAGE; - } - return LocalTransactionState.UNKNOW; - } -} diff --git a/rocketmq-example/src/main/java/com/alibaba/rocketmq/example/transaction/TransactionCheckListenerImpl.java b/rocketmq-example/src/main/java/com/alibaba/rocketmq/example/transaction/TransactionCheckListenerImpl.java index c9db61f6..a2cca41c 100644 --- a/rocketmq-example/src/main/java/com/alibaba/rocketmq/example/transaction/TransactionCheckListenerImpl.java +++ b/rocketmq-example/src/main/java/com/alibaba/rocketmq/example/transaction/TransactionCheckListenerImpl.java @@ -1,15 +1,49 @@ +/** + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package com.alibaba.rocketmq.example.transaction; +import java.util.concurrent.atomic.AtomicInteger; + import com.alibaba.rocketmq.client.producer.LocalTransactionState; import com.alibaba.rocketmq.client.producer.TransactionCheckListener; -import com.alibaba.rocketmq.common.MessageExt; +import com.alibaba.rocketmq.common.message.MessageExt; +/** + * 未决事务,服务器回查客户端 + */ public class TransactionCheckListenerImpl implements TransactionCheckListener { + private AtomicInteger transactionIndex = new AtomicInteger(0); + @Override public LocalTransactionState checkLocalTransactionState(MessageExt msg) { System.out.println("server checking TrMsg " + msg.toString()); - return LocalTransactionState.ROLLBACK_MESSAGE; + + int value = transactionIndex.getAndIncrement(); + if ((value % 6) == 0) { + throw new RuntimeException("Could not find db"); + } + else if ((value % 5) == 0) { + return LocalTransactionState.ROLLBACK_MESSAGE; + } + else if ((value % 4) == 0) { + return LocalTransactionState.COMMIT_MESSAGE; + } + + return LocalTransactionState.UNKNOW; } } diff --git a/rocketmq-example/src/main/java/com/alibaba/rocketmq/example/transaction/TransactionExecuterImpl.java b/rocketmq-example/src/main/java/com/alibaba/rocketmq/example/transaction/TransactionExecuterImpl.java new file mode 100644 index 00000000..2d1f0e6b --- /dev/null +++ b/rocketmq-example/src/main/java/com/alibaba/rocketmq/example/transaction/TransactionExecuterImpl.java @@ -0,0 +1,48 @@ +/** + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.rocketmq.example.transaction; + +import java.util.concurrent.atomic.AtomicInteger; + +import com.alibaba.rocketmq.client.producer.LocalTransactionExecuter; +import com.alibaba.rocketmq.client.producer.LocalTransactionState; +import com.alibaba.rocketmq.common.message.Message; + + +/** + * 执行本地事务 + */ +public class TransactionExecuterImpl implements LocalTransactionExecuter { + private AtomicInteger transactionIndex = new AtomicInteger(1); + + + @Override + public LocalTransactionState executeLocalTransactionBranch(final Message msg, final Object arg) { + int value = transactionIndex.getAndIncrement(); + + if (value == 0) { + throw new RuntimeException("Could not find db"); + } + else if ((value % 5) == 0) { + return LocalTransactionState.ROLLBACK_MESSAGE; + } + else if ((value % 4) == 0) { + return LocalTransactionState.COMMIT_MESSAGE; + } + + return LocalTransactionState.UNKNOW; + } +} diff --git a/rocketmq-example/src/main/java/com/alibaba/rocketmq/example/transaction/TransactionProducer.java b/rocketmq-example/src/main/java/com/alibaba/rocketmq/example/transaction/TransactionProducer.java index 5e4c7c82..ddbcad61 100644 --- a/rocketmq-example/src/main/java/com/alibaba/rocketmq/example/transaction/TransactionProducer.java +++ b/rocketmq-example/src/main/java/com/alibaba/rocketmq/example/transaction/TransactionProducer.java @@ -1,45 +1,67 @@ /** - * $Id: Producer.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.example.transaction; -import com.alibaba.rocketmq.client.exception.MQBrokerException; import com.alibaba.rocketmq.client.exception.MQClientException; -import com.alibaba.rocketmq.client.producer.DefaultMQProducer; -import com.alibaba.rocketmq.client.producer.LocalTransactionExecuter; -import com.alibaba.rocketmq.client.producer.MQProducer; import com.alibaba.rocketmq.client.producer.SendResult; import com.alibaba.rocketmq.client.producer.TransactionCheckListener; import com.alibaba.rocketmq.client.producer.TransactionMQProducer; -import com.alibaba.rocketmq.common.Message; -import com.alibaba.rocketmq.remoting.exception.RemotingException; +import com.alibaba.rocketmq.common.message.Message; /** - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * 发送事务消息例子 * */ public class TransactionProducer { - public static void main(String[] args) { - try { - TransactionCheckListener transactionCheckListener = new TransactionCheckListenerImpl(); - TransactionMQProducer producer = new TransactionMQProducer("example.producer"); - producer.setTransactionCheckListener(transactionCheckListener); - producer.start(); - - String[] tags = new String[] { "TagA", "TagB", "TagC", "TagD", "TagE" }; - TranExecuterImpl tranExecuter = new TranExecuterImpl(); - for (int i = 0; i < 100; i++) { + public static void main(String[] args) throws MQClientException, InterruptedException { + + TransactionCheckListener transactionCheckListener = new TransactionCheckListenerImpl(); + TransactionMQProducer producer = new TransactionMQProducer("please_rename_unique_group_name"); + // 事务回查最小并发数 + producer.setCheckThreadPoolMinSize(2); + // 事务回查最大并发数 + producer.setCheckThreadPoolMaxSize(2); + // 队列数 + producer.setCheckRequestHoldMax(2000); + producer.setTransactionCheckListener(transactionCheckListener); + producer.start(); + + String[] tags = new String[] { "TagA", "TagB", "TagC", "TagD", "TagE" }; + TransactionExecuterImpl tranExecuter = new TransactionExecuterImpl(); + for (int i = 0; i < 100; i++) { + try { Message msg = - new Message("TopicTest", tags[i % tags.length], "KEY" + i, ("Hello RocketMQ " + i).getBytes()); - tranExecuter.setTransactionStats(1); - producer.sendMessageInTransaction(msg, tranExecuter); - } + new Message("TopicTest", tags[i % tags.length], "KEY" + i, + ("Hello RocketMQ " + i).getBytes()); + SendResult sendResult = producer.sendMessageInTransaction(msg, tranExecuter, null); + System.out.println(sendResult); - producer.shutdown(); + Thread.sleep(10); + } + catch (MQClientException e) { + e.printStackTrace(); + } } - catch (MQClientException e) { - e.printStackTrace(); + + for (int i = 0; i < 100000; i++) { + Thread.sleep(1000); } + + producer.shutdown(); + } } diff --git a/rocketmq-namesrv/conf/brokerIps.properties b/rocketmq-namesrv/conf/brokerIps.properties deleted file mode 100644 index d221cd43..00000000 --- a/rocketmq-namesrv/conf/brokerIps.properties +++ /dev/null @@ -1 +0,0 @@ -10.232.133.133:8123;10.232.133.189:8123;10.233.123.212:8123; \ No newline at end of file diff --git a/rocketmq-namesrv/conf/orderConf.properties b/rocketmq-namesrv/conf/orderConf.properties deleted file mode 100644 index ddd60aa9..00000000 --- a/rocketmq-namesrv/conf/orderConf.properties +++ /dev/null @@ -1,3 +0,0 @@ -topic.num.JINGWEI-TMALL-SERVICE-DPC=300:64;320:64 -topic.num.JINGWEI-SNSJU-APP=300:64;320:64 -topic.num.IC-AUCTIONS=410:16;411:16;412:16;413:16 \ No newline at end of file diff --git a/rocketmq-namesrv/pom.xml b/rocketmq-namesrv/pom.xml index 645401d8..8be8690e 100644 --- a/rocketmq-namesrv/pom.xml +++ b/rocketmq-namesrv/pom.xml @@ -1,14 +1,12 @@ - + com.alibaba.rocketmq rocketmq-all - 3.0.0-SNAPSHOT + 3.0.8-SNAPSHOT 4.0.0 jar - com.alibaba.rocketmq rocketmq-namesrv rocketmq-namesrv ${project.version} @@ -23,16 +21,12 @@ rocketmq-common - org.powermock - powermock-module-junit4 + ch.qos.logback + logback-classic - org.powermock - powermock-api-easymock - - - org.easymock - easymock + ch.qos.logback + logback-core diff --git a/rocketmq-namesrv/src/main/java/com/alibaba/rocketmq/namesrv/NamesrvController.java b/rocketmq-namesrv/src/main/java/com/alibaba/rocketmq/namesrv/NamesrvController.java index 8baa627e..7df715e7 100644 --- a/rocketmq-namesrv/src/main/java/com/alibaba/rocketmq/namesrv/NamesrvController.java +++ b/rocketmq-namesrv/src/main/java/com/alibaba/rocketmq/namesrv/NamesrvController.java @@ -1,119 +1,173 @@ /** - * $Id: NamesrvController.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.namesrv; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ThreadFactory; +import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.alibaba.rocketmq.common.MixAll; +import com.alibaba.rocketmq.common.constant.LoggerName; import com.alibaba.rocketmq.common.namesrv.NamesrvConfig; -import com.alibaba.rocketmq.namesrv.daemon.NamesrvClient; -import com.alibaba.rocketmq.namesrv.daemon.NamesrvSync; -import com.alibaba.rocketmq.namesrv.daemon.PollingAddress; -import com.alibaba.rocketmq.namesrv.processor.AllRequestProcessor; -import com.alibaba.rocketmq.namesrv.topic.DefaultNamesrvConfigManager; -import com.alibaba.rocketmq.namesrv.topic.DefaultTopicRuntimeDataManager; -import com.alibaba.rocketmq.namesrv.topic.NamesrvConfigManager; -import com.alibaba.rocketmq.namesrv.topic.TopicRuntimeDataManager; +import com.alibaba.rocketmq.namesrv.kvconfig.KVConfigManager; +import com.alibaba.rocketmq.namesrv.processor.DefaultRequestProcessor; +import com.alibaba.rocketmq.namesrv.routeinfo.BrokerHousekeepingService; +import com.alibaba.rocketmq.namesrv.routeinfo.RouteInfoManager; import com.alibaba.rocketmq.remoting.RemotingServer; -import com.alibaba.rocketmq.remoting.netty.NettyClientConfig; import com.alibaba.rocketmq.remoting.netty.NettyRemotingServer; import com.alibaba.rocketmq.remoting.netty.NettyServerConfig; /** - * Name server + * Name Server服务控制 * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com - * @author lansheng.zj@taobao.com + * @author shijia.wxr + * @since 2013-7-5 */ public class NamesrvController { - private static final Logger log = LoggerFactory.getLogger(MixAll.NamesrvLoggerName); - // Name Server + private static final Logger log = LoggerFactory.getLogger(LoggerName.NamesrvLoggerName); + // Name Server配置 private final NamesrvConfig namesrvConfig; - // ͨŲ + // 通信层配置 private final NettyServerConfig nettyServerConfig; - - // nameserverͨŲ + // 服务端通信层对象 private RemotingServer remotingServer; - - // nameserver̳߳ - private ExecutorService requestsServerExecutor; - - private TopicRuntimeDataManager topicInfoManager; - private NamesrvConfigManager namesrvConfigManager; - - // namesrvͬ - private NamesrvSync namesrvSync; - // namesrvȡbroker - private NamesrvClient namesrvClient; - // ѯȡnamesrvַ - private PollingAddress pollingAddress; - - - public NamesrvController(final NamesrvConfig namesrvConfig, final NettyServerConfig nettyServerConfig, - final NettyClientConfig nettyClientConfig) { + // 接收Broker连接事件 + private BrokerHousekeepingService brokerHousekeepingService; + // 服务端网络请求处理线程池 + private ExecutorService remotingExecutor; + + // 定时线程 + private final ScheduledExecutorService scheduledExecutorService = Executors + .newSingleThreadScheduledExecutor(new ThreadFactory() { + @Override + public Thread newThread(Runnable r) { + return new Thread(r, "NamesrvControllerScheduledThread"); + } + }); + + /** + * 核心数据结构 + */ + private final KVConfigManager kvConfigManager; + private final RouteInfoManager routeInfoManager; + + + public NamesrvController(NamesrvConfig namesrvConfig, NettyServerConfig nettyServerConfig) { this.namesrvConfig = namesrvConfig; this.nettyServerConfig = nettyServerConfig; - topicInfoManager = new DefaultTopicRuntimeDataManager(namesrvConfig); - namesrvConfigManager = new DefaultNamesrvConfigManager(namesrvConfig); - namesrvSync = new NamesrvSync(namesrvConfig, topicInfoManager); - namesrvClient = new NamesrvClient(namesrvConfig, nettyClientConfig, topicInfoManager); - pollingAddress = new PollingAddress(namesrvConfig); + this.kvConfigManager = new KVConfigManager(this); + this.routeInfoManager = new RouteInfoManager(); + this.brokerHousekeepingService = new BrokerHousekeepingService(this); } public boolean initialize() { - // ӡò - MixAll.printObjectProperties(log, namesrvConfig); + // 打印服务器配置参数 + MixAll.printObjectProperties(log, this.namesrvConfig); + + // 加载KV配置 + this.kvConfigManager.load(); - // ʼͨŲ - remotingServer = new NettyRemotingServer(nettyServerConfig); + // 初始化通信层 + this.remotingServer = new NettyRemotingServer(this.nettyServerConfig, this.brokerHousekeepingService); - // ʼ̳߳ - requestsServerExecutor = + // 初始化线程池 + this.remotingExecutor = Executors.newFixedThreadPool(nettyServerConfig.getServerWorkerThreads(), new ThreadFactory() { private AtomicInteger threadIndex = new AtomicInteger(0); @Override public Thread newThread(Runnable r) { - return new Thread(r, "RequestsExecutorThread_" + threadIndex.incrementAndGet()); + return new Thread(r, "RemotingExecutorThread_" + threadIndex.incrementAndGet()); } }); - registerProcessor(); + this.registerProcessor(); + + // 增加定时任务 + this.scheduledExecutorService.scheduleAtFixedRate(new Runnable() { + + @Override + public void run() { + NamesrvController.this.routeInfoManager.scanNotActiveBroker(); + } + }, 1000 * 5, 1000 * 10, TimeUnit.MILLISECONDS); + + this.scheduledExecutorService.scheduleAtFixedRate(new Runnable() { + + @Override + public void run() { + NamesrvController.this.kvConfigManager.printAllPeriodically(); + } + }, 1000 * 10, 1000 * 120, TimeUnit.MILLISECONDS); + + this.scheduledExecutorService.scheduleAtFixedRate(new Runnable() { + + @Override + public void run() { + NamesrvController.this.routeInfoManager.printAllPeriodically(); + } + }, 1000 * 10, 1000 * 120, TimeUnit.MILLISECONDS); - return topicInfoManager.init(); + return true; } - public void registerProcessor() { - remotingServer.registerDefaultProcessor(new AllRequestProcessor(this, topicInfoManager), - this.requestsServerExecutor); + private void registerProcessor() { + this.remotingServer + .registerDefaultProcessor(new DefaultRequestProcessor(this), this.remotingExecutor); } public void start() throws Exception { - remotingServer.start(); - namesrvSync.start(); - namesrvClient.start(); - pollingAddress.start(); + this.remotingServer.start(); } public void shutdown() { - requestsServerExecutor.shutdown(); - remotingServer.shutdown(); - namesrvSync.shutdown(); - topicInfoManager.shutdown(); - namesrvClient.shutdown(); - pollingAddress.shutdown(); + this.remotingServer.shutdown(); + this.remotingExecutor.shutdown(); + this.scheduledExecutorService.shutdown(); + } + + + public NamesrvConfig getNamesrvConfig() { + return namesrvConfig; + } + + + public NettyServerConfig getNettyServerConfig() { + return nettyServerConfig; + } + + + public KVConfigManager getKvConfigManager() { + return kvConfigManager; + } + + + public RouteInfoManager getRouteInfoManager() { + return routeInfoManager; } } diff --git a/rocketmq-namesrv/src/main/java/com/alibaba/rocketmq/namesrv/NamesrvStartup.java b/rocketmq-namesrv/src/main/java/com/alibaba/rocketmq/namesrv/NamesrvStartup.java index dd377b5b..d5779cb7 100644 --- a/rocketmq-namesrv/src/main/java/com/alibaba/rocketmq/namesrv/NamesrvStartup.java +++ b/rocketmq-namesrv/src/main/java/com/alibaba/rocketmq/namesrv/NamesrvStartup.java @@ -1,5 +1,17 @@ /** - * $Id: NamesrvStartup.java 1839 2013-05-16 02:12:02Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.namesrv; @@ -15,22 +27,23 @@ import org.apache.commons.cli.PosixParser; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -//import org.apache.log4j.xml.DOMConfigurator; import ch.qos.logback.classic.LoggerContext; import ch.qos.logback.classic.joran.JoranConfigurator; +import com.alibaba.rocketmq.common.MQVersion; import com.alibaba.rocketmq.common.MixAll; +import com.alibaba.rocketmq.common.constant.LoggerName; import com.alibaba.rocketmq.common.namesrv.NamesrvConfig; -import com.alibaba.rocketmq.remoting.netty.NettyClientConfig; import com.alibaba.rocketmq.remoting.netty.NettyServerConfig; +import com.alibaba.rocketmq.remoting.protocol.RemotingCommand; /** - * Name server - * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * Name server 启动入口 * + * @author shijia.wxr + * @since 2013-7-5 */ public class NamesrvStartup { @@ -48,21 +61,23 @@ public static Options buildCommandlineOptions(final Options options) { public static void main(String[] args) { + System.setProperty(RemotingCommand.RemotingVersionKey, Integer.toString(MQVersion.CurrentVersion)); + try { - // + // 解析命令行 Options options = MixAll.buildCommandlineOptions(new Options()); final CommandLine commandLine = - MixAll.parseCmdLine("mqnamesrv", args, buildCommandlineOptions(options), new PosixParser()); + MixAll.parseCmdLine("mqnamesrv", args, buildCommandlineOptions(options), + new PosixParser()); if (null == commandLine) { System.exit(-1); return; } - // ʼļ + // 初始化配置文件 final NamesrvConfig namesrvConfig = new NamesrvConfig(); final NettyServerConfig nettyServerConfig = new NettyServerConfig(); nettyServerConfig.setListenPort(9876); - final NettyClientConfig nettyClientConfig = new NettyClientConfig(); if (commandLine.hasOption('c')) { String file = commandLine.getOptionValue('c'); if (file != null) { @@ -71,17 +86,15 @@ public static void main(String[] args) { properties.load(in); MixAll.properties2Object(properties, namesrvConfig); MixAll.properties2Object(properties, nettyServerConfig); - MixAll.properties2Object(properties, nettyClientConfig); System.out.println("load config properties file OK, " + file); in.close(); } } - // ӡĬ + // 打印默认配置 if (commandLine.hasOption('p')) { MixAll.printObjectProperties(null, namesrvConfig); MixAll.printObjectProperties(null, nettyServerConfig); - MixAll.printObjectProperties(null, nettyClientConfig); System.exit(0); } @@ -93,18 +106,16 @@ public static void main(String[] args) { System.exit(-2); } - // ʼLogback + // 初始化Logback LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory(); JoranConfigurator configurator = new JoranConfigurator(); configurator.setContext(lc); lc.reset(); - configurator.doConfigure(namesrvConfig.getRocketmqHome() + "/conf/log4j_namesrv.xml"); - - final Logger log = LoggerFactory.getLogger(MixAll.NamesrvLoggerName); + configurator.doConfigure(namesrvConfig.getRocketmqHome() + "/conf/logback_namesrv.xml"); + final Logger log = LoggerFactory.getLogger(LoggerName.NamesrvLoggerName); - // ʼƶ - final NamesrvController controller = - new NamesrvController(namesrvConfig, nettyServerConfig, nettyClientConfig); + // 初始化服务控制对象 + final NamesrvController controller = new NamesrvController(namesrvConfig, nettyServerConfig); boolean initResult = controller.initialize(); if (!initResult) { controller.shutdown(); @@ -131,7 +142,7 @@ public void run() { } }, "ShutdownHook")); - // + // 启动服务 controller.start(); String tip = "The Name Server boot success."; diff --git a/rocketmq-namesrv/src/main/java/com/alibaba/rocketmq/namesrv/common/MergeResult.java b/rocketmq-namesrv/src/main/java/com/alibaba/rocketmq/namesrv/common/MergeResult.java deleted file mode 100644 index 92f20308..00000000 --- a/rocketmq-namesrv/src/main/java/com/alibaba/rocketmq/namesrv/common/MergeResult.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.alibaba.rocketmq.namesrv.common; - -/** - * @author lansheng.zj@taobao.com - */ -public abstract class MergeResult { - /** - * ûкϲ - */ - public static final int NOT_MERGE = 0; - /** - * ϲݳɹ - */ - public static final int MERGE_SUCCESS = 1; - /** - * ϲгЧ - */ - public static final int MERGE_INVALID = 2; - /** - * ϵͳ - */ - public static final int SYS_ERROR = 3; -} diff --git a/rocketmq-namesrv/src/main/java/com/alibaba/rocketmq/namesrv/common/MergeResultHolder.java b/rocketmq-namesrv/src/main/java/com/alibaba/rocketmq/namesrv/common/MergeResultHolder.java deleted file mode 100644 index 953c0ff9..00000000 --- a/rocketmq-namesrv/src/main/java/com/alibaba/rocketmq/namesrv/common/MergeResultHolder.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.alibaba.rocketmq.namesrv.common; - -public class MergeResultHolder { - - private int result; - - - public MergeResultHolder() { - result = 0; - } - - - public int getResult() { - return result; - } - - - public void setResult(int result) { - this.result = result; - } -} diff --git a/rocketmq-namesrv/src/main/java/com/alibaba/rocketmq/namesrv/common/Result.java b/rocketmq-namesrv/src/main/java/com/alibaba/rocketmq/namesrv/common/Result.java deleted file mode 100644 index cbb6fd80..00000000 --- a/rocketmq-namesrv/src/main/java/com/alibaba/rocketmq/namesrv/common/Result.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.alibaba.rocketmq.namesrv.common; - -/** - * @auther lansheng.zj@taobao.com - */ -public class Result { - - public static Result SUCCESS = new Result(true, "SUCCESS"); - private boolean success; - private String detail; - - - public Result(boolean success, String detail) { - this.success = success; - this.detail = detail; - } - - - public boolean isSuccess() { - return success; - } - - - public String getDetail() { - return detail; - } - - - @Override - public String toString() { - return "success=" + success + ",detail=" + detail; - } -} diff --git a/rocketmq-namesrv/src/main/java/com/alibaba/rocketmq/namesrv/daemon/NamesrvClient.java b/rocketmq-namesrv/src/main/java/com/alibaba/rocketmq/namesrv/daemon/NamesrvClient.java deleted file mode 100644 index 864fa6fd..00000000 --- a/rocketmq-namesrv/src/main/java/com/alibaba/rocketmq/namesrv/daemon/NamesrvClient.java +++ /dev/null @@ -1,314 +0,0 @@ -package com.alibaba.rocketmq.namesrv.daemon; - -import static com.alibaba.rocketmq.common.MixAll.Localhost; -import static com.alibaba.rocketmq.common.protocol.route.ObjectConverter.props2TopicConfigTable; -import static com.alibaba.rocketmq.common.protocol.MQProtos.MQRequestCode.GET_ALL_TOPIC_CONFIG_VALUE; -import static com.alibaba.rocketmq.remoting.protocol.RemotingProtos.ResponseCode.SUCCESS_VALUE; - -import io.netty.channel.Channel; - -import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; -import java.io.ByteArrayInputStream; -import java.util.HashMap; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Properties; -import java.util.concurrent.Future; -import java.util.concurrent.ThreadFactory; -import java.util.concurrent.atomic.AtomicInteger; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.alibaba.rocketmq.common.MixAll; -import com.alibaba.rocketmq.common.ServiceThread; -import com.alibaba.rocketmq.common.TopicConfig; -import com.alibaba.rocketmq.common.namesrv.NamesrvConfig; -import com.alibaba.rocketmq.common.protocol.header.namesrv.GetTopicResponseHeader; -import com.alibaba.rocketmq.common.protocol.route.QueueData; -import com.alibaba.rocketmq.namesrv.common.Result; -import com.alibaba.rocketmq.namesrv.sync.Exec; -import com.alibaba.rocketmq.namesrv.sync.FutureGroup; -import com.alibaba.rocketmq.namesrv.sync.TaskGroup; -import com.alibaba.rocketmq.namesrv.sync.TaskGroupExecutor; -import com.alibaba.rocketmq.namesrv.topic.TopicRuntimeDataManager; -import com.alibaba.rocketmq.remoting.ChannelEventListener; -import com.alibaba.rocketmq.remoting.RemotingClient; -import com.alibaba.rocketmq.remoting.netty.NettyClientConfig; -import com.alibaba.rocketmq.remoting.netty.NettyRemotingClient; -import com.alibaba.rocketmq.remoting.protocol.RemotingCommand; - - -/** - * ʱbrokerȡtopicϢ߳ - * - * @author lansheng.zj@taobao.com - */ -public class NamesrvClient extends ServiceThread { - - private static final Logger log = LoggerFactory.getLogger(MixAll.NamesrvLoggerName); - public static final int MAX_RETRIES = 3; - private TaskGroupExecutor reqBrokerGroupExecutor; - private TaskGroup reqTaskGroup; - private TopicRuntimeDataManager topicRuntimeDataManager; - private RemotingClient remotingClient; - private NettyClientConfig nettyClientConfig; - private NamesrvConfig namesrvConf; - - - public NamesrvClient(NamesrvConfig nameConf, NettyClientConfig nettyConfig, - TopicRuntimeDataManager runtimeDataManager) { - namesrvConf = nameConf; - topicRuntimeDataManager = runtimeDataManager; - nettyClientConfig = nettyConfig; - remotingClient = new NettyRemotingClient(nettyClientConfig, new ChannelEventListener() { - - @Override - public void onChannelConnect(String remoteAddr, Channel channel) { - // ignore - } - - - @Override - public void onChannelClose(String remoteAddr, Channel channel) { - // unregister broker topic info when channel close - unRegisterBrokerTopic(remoteAddr); - } - - - @Override - public void onChannelException(String remoteAddr, Channel channel) { - // unregister broker topic info when channel exception - unRegisterBrokerTopic(remoteAddr); - } - - }); - - reqTaskGroup = createTaskGroup(); - reqBrokerGroupExecutor = new TaskGroupExecutor(new ThreadFactory() { - - private AtomicInteger index = new AtomicInteger(0); - - - @Override - public Thread newThread(Runnable r) { - return new Thread(r, "reqbroker-taskgroup-executor-" + index.getAndIncrement()); - } - }); - - topicRuntimeDataManager.addPropertyChangeListener("brokerList", new PropertyChangeListener() { - - @Override - public void propertyChange(PropertyChangeEvent evt) { - reqTaskGroup = createTaskGroup(); - } - - }); - } - - - private TaskGroup createTaskGroup() { - TaskGroup taskGroup = new TaskGroup(); - for (String address : topicRuntimeDataManager.getBrokerList()) { - taskGroup.addTask(address, createTask(address)); - } - - return taskGroup; - } - - - private Exec createTask(final String address) { - return new Exec() { - - @Override - public void beforeExec() { - // TODO - } - - - @Override - public Boolean doExec(Object param) throws Exception { - return NamesrvClient.this.requestBrokerTopicConf(address); - } - }; - } - - - public boolean requestBrokerTopicConf(String address) throws Exception { - boolean success = false; - int reties = 0; - if (null == address || "".equals(address)) { - log.error("request broker topic error because addr is blank, check broker addr retrieve"); - return success; - } - - RemotingCommand request = RemotingCommand.createRequestCommand(GET_ALL_TOPIC_CONFIG_VALUE, null); - - while (!success && reties++ <= MAX_RETRIES) { - try { - RemotingCommand response = - remotingClient.invokeSync(address, request, namesrvConf.getPullFormBrokerTimeout()); - if (SUCCESS_VALUE == response.getCode()) { - GetTopicResponseHeader responseHeader = - (GetTopicResponseHeader) response - .decodeCommandCustomHeader(GetTopicResponseHeader.class); - // String version = responseHeader.getVersion(); - // TODO charset problem - byte[] data = response.getBody(); - ByteArrayInputStream inputStream = new ByteArrayInputStream(data); - Properties props = new Properties(); - props.load(inputStream); - Map snapshot = props2TopicConfigTable(props, null); - Map queueDataMap = - topicConfigMap2QueueDataMap(snapshot, responseHeader.getBrokerName()); - // ϲbrokerȡtopicϢ - topicRuntimeDataManager.mergeQueueData(queueDataMap); - // ϲbrokerDataϢ - topicRuntimeDataManager.mergeBrokerData(responseHeader.getBrokerName(), - responseHeader.getBrokerId(), address); - - success = true; - } - else { - // record failure - log.error("get all topic config from broker(" + address + ") fail, code:" + response.getCode() - + ", remark:" + response.getRemark()); - success = false; - } - } - catch (Exception e) { - if (MAX_RETRIES == reties) { - log.error("request broker(" + address + ") topic fail finally"); - break; - } - - log.error("request broker(" + address + ") topic fail, retry " + reties, e); - Thread.sleep(500); - } - } - return success; - } - - - public boolean unRegisterBrokerTopic(String address) { - if (null == address || "".equals(address)) - return false; - - RemotingCommand rc = topicRuntimeDataManager.unRegisterBrokerByAddr(address); - if (rc.getCode() == SUCCESS_VALUE) - return true; - - // log - return false; - } - - - private Map topicConfigMap2QueueDataMap(Map map, String brokerName) { - Map queueDataMap = new HashMap(); - for (Entry entry : map.entrySet()) { - QueueData queueData = new QueueData(); - queueData.setBrokerName(brokerName); - queueData.setPerm(entry.getValue().getPerm()); - queueData.setReadQueueNums(entry.getValue().getReadQueueNums()); - queueData.setWriteQueueNums(entry.getValue().getWriteQueueNums()); - queueDataMap.put(entry.getKey(), queueData); - } - - return queueDataMap; - } - - - public FutureGroup groupCommit() { - return reqBrokerGroupExecutor.groupCommit(reqTaskGroup, null); - } - - - @Override - public void run() { - - try { - // initial delay - Thread.sleep(2000L); - } - catch (InterruptedException e) { - // TODO - log.error("namesrvclient initial delay interruped.", e); - } - - while (!isStoped()) { - try { - waitForRunning(namesrvConf.getPullFormBrokerInterval()); - FutureGroup futureGroup = groupCommit(); - Result result = futureGroup.await(namesrvConf.getPullFormBrokerTimeout()); - if (result.isSuccess()) { - Result pullResult = pullSuccess(futureGroup); - if (pullResult.isSuccess()) { - // TODO all success - - } - else { - // someone fail - log.error("merge broker topic conf not all success. detail:\n" + pullResult.getDetail()); - } - } - else { - // ʱ - log.error("merge broker topic conf timeout. detail:\n" + result.getDetail()); - } - } - catch (Exception e) { - // error handler - log.error("NamesrvClient.run exception.", e); - } - } - } - - - public Result pullSuccess(FutureGroup future) { - Result result = Result.SUCCESS; - try { - for (Entry> entry : future.getResultMap().entrySet()) { - if (!entry.getValue().get().booleanValue()) { - result = new Result(false, future.detailInfo()); - break; - } - } - } - catch (Exception e) { - log.error("NamesrvClient.pullSuccess exception", e); - result = new Result(false, Localhost + " NamesrvClient.pullSuccess exception" + e.getMessage()); - } - - return result; - } - - - @Override - public void start() { - remotingClient.start(); - super.start(); - } - - - @Override - public void stop() { - super.stop(); - remotingClient.shutdown(); - - } - - - @Override - public void stop(boolean interrupt) { - super.stop(interrupt); - remotingClient.shutdown(); - } - - - @Override - public String getServiceName() { - return "namesrv-polling-broker"; - } - -} diff --git a/rocketmq-namesrv/src/main/java/com/alibaba/rocketmq/namesrv/daemon/NamesrvSync.java b/rocketmq-namesrv/src/main/java/com/alibaba/rocketmq/namesrv/daemon/NamesrvSync.java deleted file mode 100644 index 45e33282..00000000 --- a/rocketmq-namesrv/src/main/java/com/alibaba/rocketmq/namesrv/daemon/NamesrvSync.java +++ /dev/null @@ -1,205 +0,0 @@ -package com.alibaba.rocketmq.namesrv.daemon; - -import static com.alibaba.rocketmq.common.protocol.MQProtos.MQRequestCode.SYNC_NAMESRV_RUNTIME_CONF_VALUE; -import static com.alibaba.rocketmq.namesrv.common.MergeResult.MERGE_INVALID; -import static com.alibaba.rocketmq.namesrv.common.MergeResult.MERGE_SUCCESS; -import static com.alibaba.rocketmq.namesrv.common.MergeResult.NOT_MERGE; -import static com.alibaba.rocketmq.namesrv.common.MergeResult.SYS_ERROR; -import static com.alibaba.rocketmq.remoting.protocol.RemotingProtos.ResponseCode.SUCCESS_VALUE; - -import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; -import java.util.concurrent.ThreadFactory; -import java.util.concurrent.atomic.AtomicInteger; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.alibaba.rocketmq.common.MixAll; -import com.alibaba.rocketmq.common.ServiceThread; -import com.alibaba.rocketmq.common.namesrv.NamesrvConfig; -import com.alibaba.rocketmq.common.namesrv.TopicRuntimeData; -import com.alibaba.rocketmq.namesrv.common.Result; -import com.alibaba.rocketmq.namesrv.sync.Exec; -import com.alibaba.rocketmq.namesrv.sync.FutureGroup; -import com.alibaba.rocketmq.namesrv.sync.TaskGroup; -import com.alibaba.rocketmq.namesrv.sync.TaskGroupExecutor; -import com.alibaba.rocketmq.namesrv.topic.TopicRuntimeDataManager; -import com.alibaba.rocketmq.remoting.common.RemotingHelper; -import com.alibaba.rocketmq.remoting.protocol.RemotingCommand; - - -/** - * namesrvȺڵͬ - * - * @author lansheng.zj@taobao.com - */ -public class NamesrvSync extends ServiceThread { - - private static final Logger log = LoggerFactory.getLogger(MixAll.NamesrvLoggerName); - private TaskGroupExecutor syncTaskGroupExecutor; - private TopicRuntimeDataManager topicRuntimeDataManager; - private NamesrvConfig namesrvConf; - private TaskGroup syncTaskGroup; - - - public NamesrvSync(NamesrvConfig namesrvConf, TopicRuntimeDataManager topicRuntimeDataManager) { - this.namesrvConf = namesrvConf; - this.topicRuntimeDataManager = topicRuntimeDataManager; - syncTaskGroup = createTaskGroup(); - syncTaskGroupExecutor = new TaskGroupExecutor(new ThreadFactory() { - - private AtomicInteger index = new AtomicInteger(0); - - - @Override - public Thread newThread(Runnable r) { - return new Thread(r, "sync-taskgroup-executor-" + index.getAndIncrement()); - } - }); - } - - - private TaskGroup createTaskGroup() { - TaskGroup taskGroup = new TaskGroup(); - String namesrv = namesrvConf.getNamesrvAddr(); - if (null != namesrv && !"".equals(namesrv)) { - String[] addresses = namesrv.split(";"); - for (String address : addresses) { - // ųע - if (!MixAll.isLocalAddr(address)) { - taskGroup.addTask(address, createTask(address)); - } - } - } - - return taskGroup; - } - - - public void init() { - namesrvConf.addPropertyChangeListener("namesrvAddr", new PropertyChangeListener() { - @Override - public void propertyChange(PropertyChangeEvent evt) { - // copyOnWirte - syncTaskGroup = createTaskGroup(); - } - }); - } - - - private Exec createTask(final String address) { - - return new Exec() { - - @Override - public void beforeExec() { - // TODO log - - } - - - @Override - public Object doExec(Object object) throws Exception { - - // ͬڵݣȡʽֻͬnamesrvϳ־û - - RemotingCommand request = RemotingCommand.createRequestCommand(SYNC_NAMESRV_RUNTIME_CONF_VALUE, null); - RemotingCommand response = - RemotingHelper.invokeSync(address, request, namesrvConf.getSyncTimeout()); - - if (SUCCESS_VALUE == response.getCode()) { - byte[] data = response.getBody(); - TopicRuntimeData topicRuntimeData = TopicRuntimeData.decode(data); - - // ϲ,ͬkeyݲͬɾݣ⣬ûɾɾ - int code = topicRuntimeDataManager.merge(topicRuntimeData); - switch (code) { - case NOT_MERGE: - // TODO ͳ - break; - case MERGE_SUCCESS: - // TODO ͳ - break; - case MERGE_INVALID: - // TODO - break; - case SYS_ERROR: - // TODO - break; - default: - } - } - else { - // TODO - } - - return null; - } - - }; - } - - - public FutureGroup groupCommit() { - return syncTaskGroupExecutor.groupCommit(syncTaskGroup, null); - } - - - @Override - public void run() { - - try { - // initial delay - Thread.sleep(2000L); - } - catch (InterruptedException e) { - log.error("namesrv sync initial delay interrupted.", e); - } - - while (!isStoped()) { - try { - FutureGroup futureGroup = groupCommit(); - long timeout = namesrvConf.getSyncTimeout(); - Result result = futureGroup.await(timeout); - if (!result.isSuccess()) { - // ʱδر - log.error("namesrv sync timeout(" + timeout + "). detail:" + result.getDetail()); - } - - this.waitForRunning(namesrvConf.getSyncInterval()); - } - catch (Exception e) { - // exception handler - log.error("namesrv sync exception.", e); - } - } - } - - - @Override - public String getServiceName() { - return "namesrv-sync"; - } - - - public void shutdown() { - super.shutdown(); - syncTaskGroupExecutor.shutdown(); - } - - - @Override - public void stop() { - super.stop(); - syncTaskGroupExecutor.shutdown(); - } - - - @Override - public void stop(boolean interrupt) { - super.stop(interrupt); - syncTaskGroupExecutor.shutdown(); - } - -} diff --git a/rocketmq-namesrv/src/main/java/com/alibaba/rocketmq/namesrv/daemon/PollingAddress.java b/rocketmq-namesrv/src/main/java/com/alibaba/rocketmq/namesrv/daemon/PollingAddress.java deleted file mode 100644 index 32fc375f..00000000 --- a/rocketmq-namesrv/src/main/java/com/alibaba/rocketmq/namesrv/daemon/PollingAddress.java +++ /dev/null @@ -1,69 +0,0 @@ -package com.alibaba.rocketmq.namesrv.daemon; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.alibaba.rocketmq.common.MixAll; -import com.alibaba.rocketmq.common.ServiceThread; -import com.alibaba.rocketmq.common.namesrv.NamesrvConfig; -import com.alibaba.rocketmq.common.namesrv.TopAddressing; - - -/** - * ѵȡweb servernamesrvбϢ - * - * @author lansheng.zj@taobao.com - */ -public class PollingAddress extends ServiceThread { - private static final Logger log = LoggerFactory.getLogger(MixAll.NamesrvLoggerName); - - private NamesrvConfig namesrvConfig; - private TopAddressing topAddressing; - - - public PollingAddress(NamesrvConfig config) { - namesrvConfig = config; - topAddressing = new TopAddressing(); - } - - - public String fetchAddr() { - return topAddressing.fetchNSAddr(); - } - - - public void setAddrAndFireChange(String addrs) { - String old = namesrvConfig.getNamesrvAddr(); - namesrvConfig.setNamesrvAddr(addrs); - namesrvConfig.firePropertyChange("namesrvAddr", old, addrs); - } - - - @Override - public void run() { - // ʱֶˣҪͨwebserver̬ĻȡnamesrvȺַ - if(null!=namesrvConfig.getNamesrvAddr() && !"".equals(namesrvConfig.getNamesrvAddr())) { - return ; - } - - while (!isStoped()) { - String addrs = fetchAddr(); - if (null != addrs && !addrs.equals(namesrvConfig.getNamesrvAddr())) { - setAddrAndFireChange(addrs); - - if (log.isInfoEnabled()) { - log.info("poll address from web server, addrs=" + addrs); - } - } - - waitForRunning(namesrvConfig.getAddressInterval()); - } - } - - - @Override - public String getServiceName() { - return "namesrv-polling-address"; - } - -} diff --git a/rocketmq-namesrv/src/main/java/com/alibaba/rocketmq/namesrv/kvconfig/KVConfigManager.java b/rocketmq-namesrv/src/main/java/com/alibaba/rocketmq/namesrv/kvconfig/KVConfigManager.java new file mode 100644 index 00000000..d51c8193 --- /dev/null +++ b/rocketmq-namesrv/src/main/java/com/alibaba/rocketmq/namesrv/kvconfig/KVConfigManager.java @@ -0,0 +1,268 @@ +/** + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.rocketmq.namesrv.kvconfig; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.locks.ReadWriteLock; +import java.util.concurrent.locks.ReentrantReadWriteLock; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.alibaba.rocketmq.common.MixAll; +import com.alibaba.rocketmq.common.constant.LoggerName; +import com.alibaba.rocketmq.common.protocol.body.KVTable; +import com.alibaba.rocketmq.namesrv.NamesrvController; + + +/** + * KV配置管理 + * + * @author shijia.wxr + * @since 2013-7-1 + */ +public class KVConfigManager { + private static final Logger log = LoggerFactory.getLogger(LoggerName.NamesrvLoggerName); + + private final NamesrvController namesrvController; + + private final ReadWriteLock lock = new ReentrantReadWriteLock(); + private final HashMap> configTable = + new HashMap>(); + + + public KVConfigManager(NamesrvController namesrvController) { + this.namesrvController = namesrvController; + } + + + public void load() { + String content = MixAll.file2String(this.namesrvController.getNamesrvConfig().getKvConfigPath()); + if (content != null) { + KVConfigSerializeWrapper kvConfigSerializeWrapper = + KVConfigSerializeWrapper.fromJson(content, KVConfigSerializeWrapper.class); + if (null != kvConfigSerializeWrapper) { + this.configTable.putAll(kvConfigSerializeWrapper.getConfigTable()); + log.info("load KV config table OK"); + } + } + } + + + public void putKVConfig(final String namespace, final String key, final String value) { + try { + this.lock.writeLock().lockInterruptibly(); + try { + HashMap kvTable = this.configTable.get(namespace); + if (null == kvTable) { + kvTable = new HashMap(); + this.configTable.put(namespace, kvTable); + log.info("putKVConfig create new Namespace {}", namespace); + } + + final String prev = kvTable.put(key, value); + if (null != prev) { + log.info("putKVConfig update config item, Namespace: {} Key: {} Value: {}", // + namespace, key, value); + } + else { + log.info("putKVConfig create new config item, Namespace: {} Key: {} Value: {}", // + namespace, key, value); + } + } + finally { + this.lock.writeLock().unlock(); + } + } + catch (InterruptedException e) { + log.error("putKVConfig InterruptedException", e); + } + + this.persist(); + } + + + public void deleteKVConfig(final String namespace, final String key) { + try { + this.lock.writeLock().lockInterruptibly(); + try { + HashMap kvTable = this.configTable.get(namespace); + if (null != kvTable) { + String value = kvTable.remove(key); + log.info("deleteKVConfig delete a config item, Namespace: {} Key: {} Value: {}", // + namespace, key, value); + } + } + finally { + this.lock.writeLock().unlock(); + } + } + catch (InterruptedException e) { + log.error("deleteKVConfig InterruptedException", e); + } + + this.persist(); + } + + + public byte[] getKVListByNamespace(final String namespace) { + try { + this.lock.readLock().lockInterruptibly(); + try { + HashMap kvTable = this.configTable.get(namespace); + if (null != kvTable) { + KVTable table = new KVTable(); + table.setTable(kvTable); + return table.encode(); + } + } + finally { + this.lock.readLock().unlock(); + } + } + catch (InterruptedException e) { + log.error("getKVListByNamespace InterruptedException", e); + } + + return null; + } + + + public String getKVConfig(final String namespace, final String key) { + try { + this.lock.readLock().lockInterruptibly(); + try { + HashMap kvTable = this.configTable.get(namespace); + if (null != kvTable) { + return kvTable.get(key); + } + } + finally { + this.lock.readLock().unlock(); + } + } + catch (InterruptedException e) { + log.error("getKVConfig InterruptedException", e); + } + + return null; + } + + + public String getKVConfigByValue(final String namespace, final String value) { + try { + this.lock.readLock().lockInterruptibly(); + try { + HashMap kvTable = this.configTable.get(namespace); + if (null != kvTable) { + StringBuilder sb = new StringBuilder(); + String splitor = ""; + for (Map.Entry entry : kvTable.entrySet()) { + if (value.equals(entry.getValue())) { + sb.append(splitor).append(entry.getKey()); + splitor = ";"; + } + } + return sb.toString(); + } + } + finally { + this.lock.readLock().unlock(); + } + } + catch (InterruptedException e) { + log.error("getIpsByProjectGroup InterruptedException", e); + } + + return null; + } + + + public void deleteKVConfigByValue(final String namespace, final String value) { + try { + this.lock.writeLock().lockInterruptibly(); + try { + HashMap kvTable = this.configTable.get(namespace); + if (null != kvTable) { + HashMap cloneKvTable = new HashMap(kvTable); + for (Map.Entry entry : cloneKvTable.entrySet()) { + if (value.equals(entry.getValue())) { + kvTable.remove(entry.getKey()); + } + } + log.info("deleteIpsByProjectGroup delete a config item, Namespace: {} Key: {} Value: {}", // + namespace, value); + } + } + finally { + this.lock.writeLock().unlock(); + } + } + catch (InterruptedException e) { + log.error("deleteIpsByProjectGroup InterruptedException", e); + } + + this.persist(); + } + + + public void persist() { + try { + this.lock.readLock().lockInterruptibly(); + try { + KVConfigSerializeWrapper kvConfigSerializeWrapper = new KVConfigSerializeWrapper(); + kvConfigSerializeWrapper.setConfigTable(this.configTable); + + String content = kvConfigSerializeWrapper.toJson(); + + if (null != content) { + MixAll.string2File(content, this.namesrvController.getNamesrvConfig().getKvConfigPath()); + } + } + catch (IOException e) { + log.error("persist kvconfig Exception, " + + this.namesrvController.getNamesrvConfig().getKvConfigPath(), e); + } + finally { + this.lock.readLock().unlock(); + } + } + catch (InterruptedException e) { + log.error("persist InterruptedException", e); + } + + } + + + public void printAllPeriodically() { + try { + this.lock.readLock().lockInterruptibly(); + try { + log.info("--------------------------------------------------------"); + + log.info("KVConfigManager {}", this.configTable); + } + finally { + this.lock.readLock().unlock(); + } + } + catch (InterruptedException e) { + log.error("printAllPeriodically InterruptedException", e); + } + } +} diff --git a/rocketmq-namesrv/src/main/java/com/alibaba/rocketmq/namesrv/kvconfig/KVConfigSerializeWrapper.java b/rocketmq-namesrv/src/main/java/com/alibaba/rocketmq/namesrv/kvconfig/KVConfigSerializeWrapper.java new file mode 100644 index 00000000..605ea68c --- /dev/null +++ b/rocketmq-namesrv/src/main/java/com/alibaba/rocketmq/namesrv/kvconfig/KVConfigSerializeWrapper.java @@ -0,0 +1,41 @@ +/** + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.rocketmq.namesrv.kvconfig; + +import java.util.HashMap; + +import com.alibaba.rocketmq.remoting.protocol.RemotingSerializable; + + +/** + * KV配置序列化,json包装 + * + * @author shijia.wxr + * @since 2013-7-25 + */ +public class KVConfigSerializeWrapper extends RemotingSerializable { + private HashMap> configTable; + + + public HashMap> getConfigTable() { + return configTable; + } + + + public void setConfigTable(HashMap> configTable) { + this.configTable = configTable; + } +} diff --git a/rocketmq-namesrv/src/main/java/com/alibaba/rocketmq/namesrv/processor/AllRequestProcessor.java b/rocketmq-namesrv/src/main/java/com/alibaba/rocketmq/namesrv/processor/AllRequestProcessor.java deleted file mode 100644 index f7bcf4cd..00000000 --- a/rocketmq-namesrv/src/main/java/com/alibaba/rocketmq/namesrv/processor/AllRequestProcessor.java +++ /dev/null @@ -1,109 +0,0 @@ -/** - * $Id: AllRequestProcessor.java 1831 2013-05-16 01:39:51Z shijia.wxr $ - */ -package com.alibaba.rocketmq.namesrv.processor; - -import io.netty.channel.ChannelHandlerContext; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.alibaba.rocketmq.common.MixAll; -import com.alibaba.rocketmq.common.protocol.MQProtos.MQRequestCode; -import com.alibaba.rocketmq.common.protocol.header.namesrv.GetRouteInfoRequestHeader; -import com.alibaba.rocketmq.common.protocol.header.namesrv.RegisterBrokerRequestHeader; -import com.alibaba.rocketmq.common.protocol.header.namesrv.RegisterOrderTopicRequestHeader; -import com.alibaba.rocketmq.common.protocol.header.namesrv.UnRegisterBrokerRequestHeader; -import com.alibaba.rocketmq.namesrv.NamesrvController; -import com.alibaba.rocketmq.namesrv.topic.TopicRuntimeDataManager; -import com.alibaba.rocketmq.remoting.exception.RemotingCommandException; -import com.alibaba.rocketmq.remoting.netty.NettyRequestProcessor; -import com.alibaba.rocketmq.remoting.protocol.RemotingCommand; - - -/** - * @author vintage.wang@gmail.com shijia.wxr@taobao.com - * @author lansheng.zj@taobao.com - */ -public class AllRequestProcessor implements NettyRequestProcessor { - private static final Logger log = LoggerFactory.getLogger(MixAll.NamesrvLoggerName); - - private final NamesrvController namesrvController; - private TopicRuntimeDataManager topicInfoManager; - - - public AllRequestProcessor(final NamesrvController namesrvController, TopicRuntimeDataManager topicInfoManager) { - this.namesrvController = namesrvController; - this.topicInfoManager = topicInfoManager; - } - - - @Override - public RemotingCommand processRequest(ChannelHandlerContext ctx, RemotingCommand request) - throws RemotingCommandException { - MQRequestCode code = MQRequestCode.valueOf(request.getCode()); - switch (code) { - case REGISTER_BROKER: - RegisterBrokerRequestHeader requestBrokerHeader = - (RegisterBrokerRequestHeader) request - .decodeCommandCustomHeader(RegisterBrokerRequestHeader.class); - return topicInfoManager.registerBroker(requestBrokerHeader.getBrokerAddr()); - - case REGISTER_BROKER_SINGLE: - RegisterBrokerRequestHeader requestBrokerSingleHeader = - (RegisterBrokerRequestHeader) request - .decodeCommandCustomHeader(RegisterBrokerRequestHeader.class); - return topicInfoManager.registerBrokerSingle(requestBrokerSingleHeader.getBrokerAddr()); - - case UNREGISTER_BROKER: - UnRegisterBrokerRequestHeader unRequestBrokerHeader = - (UnRegisterBrokerRequestHeader) request - .decodeCommandCustomHeader(UnRegisterBrokerRequestHeader.class); - return topicInfoManager.unRegisterBroker(unRequestBrokerHeader.getBrokerName()); - case UNREGISTER_BROKER_SINGLE: - UnRegisterBrokerRequestHeader unRequestBrokerSingleHeader = - (UnRegisterBrokerRequestHeader) request - .decodeCommandCustomHeader(UnRegisterBrokerRequestHeader.class); - - return topicInfoManager.unRegisterBrokerSingle(unRequestBrokerSingleHeader.getBrokerName()); - case GET_BROKER_LIST: - break; - case REGISTER_ORDER_TOPIC: - RegisterOrderTopicRequestHeader registerOrderTopicHeader = - (RegisterOrderTopicRequestHeader) request - .decodeCommandCustomHeader(RegisterOrderTopicRequestHeader.class); - return topicInfoManager.registerOrderTopic(registerOrderTopicHeader.getTopic(), - registerOrderTopicHeader.getOrderTopicString()); - - case REGISTER_ORDER_TOPIC_SINGLE: - RegisterOrderTopicRequestHeader registerOrderTopicSingleHeader = - (RegisterOrderTopicRequestHeader) request - .decodeCommandCustomHeader(RegisterOrderTopicRequestHeader.class); - return topicInfoManager.registerOrderTopicSingle(registerOrderTopicSingleHeader.getTopic(), - registerOrderTopicSingleHeader.getOrderTopicString()); - - case UNREGISTER_ORDER_TOPIC: - break; - case GET_ORDER_TOPIC_LIST: - break; - case UPDATE_NAMESRV_CONFIG: - break; - case GET_NAMESRV_CONFIG: - break; - case GET_NAMESRV_RUNTIME_INFO: - break; - case GET_ROUTEINTO_BY_TOPIC: - GetRouteInfoRequestHeader getRouteInfoHeader = - (GetRouteInfoRequestHeader) request.decodeCommandCustomHeader(GetRouteInfoRequestHeader.class); - return topicInfoManager.getRouteInfoByTopic(getRouteInfoHeader.getTopic()); - - case SYNC_NAMESRV_RUNTIME_CONF: - return topicInfoManager.getTopicRuntimeData(); - - default: - break; - } - - return null; - } -} diff --git a/rocketmq-namesrv/src/main/java/com/alibaba/rocketmq/namesrv/processor/ChangeSpreadProcessor.java b/rocketmq-namesrv/src/main/java/com/alibaba/rocketmq/namesrv/processor/ChangeSpreadProcessor.java deleted file mode 100644 index 1282a50a..00000000 --- a/rocketmq-namesrv/src/main/java/com/alibaba/rocketmq/namesrv/processor/ChangeSpreadProcessor.java +++ /dev/null @@ -1,250 +0,0 @@ -package com.alibaba.rocketmq.namesrv.processor; - -import static com.alibaba.rocketmq.common.protocol.MQProtos.MQRequestCode.REGISTER_BROKER_SINGLE_VALUE; -import static com.alibaba.rocketmq.common.protocol.MQProtos.MQRequestCode.REGISTER_ORDER_TOPIC_SINGLE_VALUE; -import static com.alibaba.rocketmq.namesrv.sync.TaskType.REG_BROKER; -import static com.alibaba.rocketmq.namesrv.sync.TaskType.REG_TOPIC; -import static com.alibaba.rocketmq.namesrv.sync.TaskType.UNREG_BROKER; -import static com.alibaba.rocketmq.remoting.protocol.RemotingProtos.ResponseCode.SUCCESS_VALUE; - -import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; -import java.util.HashMap; -import java.util.Map; -import java.util.concurrent.ThreadFactory; -import java.util.concurrent.atomic.AtomicInteger; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.alibaba.rocketmq.common.MixAll; -import com.alibaba.rocketmq.common.namesrv.NamesrvConfig; -import com.alibaba.rocketmq.common.protocol.MQProtos.MQRequestCode; -import com.alibaba.rocketmq.common.protocol.header.namesrv.RegisterBrokerRequestHeader; -import com.alibaba.rocketmq.common.protocol.header.namesrv.RegisterOrderTopicRequestHeader; -import com.alibaba.rocketmq.common.protocol.header.namesrv.UnRegisterBrokerRequestHeader; -import com.alibaba.rocketmq.namesrv.common.Result; -import com.alibaba.rocketmq.namesrv.sync.Exec; -import com.alibaba.rocketmq.namesrv.sync.FutureGroup; -import com.alibaba.rocketmq.namesrv.sync.TaskGroup; -import com.alibaba.rocketmq.namesrv.sync.TaskGroupExecutor; -import com.alibaba.rocketmq.namesrv.sync.TaskType; -import com.alibaba.rocketmq.remoting.common.RemotingHelper; -import com.alibaba.rocketmq.remoting.protocol.RemotingCommand; - - -/** - * @author lansheng.zj@taobao.com - */ -public class ChangeSpreadProcessor { - - private static final Logger log = LoggerFactory.getLogger(MixAll.NamesrvLoggerName); - private Map> taskGroupMap; - private TaskGroupExecutor clientTaskGroupExecutor; - private NamesrvConfig namesrvConf; - - - public ChangeSpreadProcessor(NamesrvConfig namesrvConf) { - this.namesrvConf = namesrvConf; - taskGroupMap = createTaskMap(); - clientTaskGroupExecutor = new TaskGroupExecutor(new ThreadFactory() { - - private AtomicInteger index = new AtomicInteger(0); - - - @Override - public Thread newThread(Runnable r) { - return new Thread(r, "client-taskgroup-executor-" + index.getAndIncrement()); - } - }); - } - - - public void init() { - namesrvConf.addPropertyChangeListener("namesrvAddr", new PropertyChangeListener() { - @Override - public void propertyChange(PropertyChangeEvent evt) { - // copyOnWirte - taskGroupMap = createTaskMap(); - } - }); - } - - - public Map> createTaskMap() { - Map> map = new HashMap>(); - map.put(REG_BROKER, createTaskGroup(REG_BROKER)); - map.put(REG_TOPIC, createTaskGroup(REG_TOPIC)); - map.put(UNREG_BROKER, createTaskGroup(UNREG_BROKER)); - return map; - } - - - public FutureGroup spreadChange(int type, String[] values) { - TaskGroup taskGroup = null; - switch (type) { - case REG_BROKER: - taskGroup = taskGroupMap.get(REG_BROKER); - break; - case REG_TOPIC: - taskGroup = taskGroupMap.get(REG_TOPIC); - break; - case UNREG_BROKER: - taskGroup = taskGroupMap.get(UNREG_BROKER); - break; - default: - // TODO - } - - return clientTaskGroupExecutor.groupCommit(taskGroup, values); - } - - - /** - * - * - * @param type - * {@link TaskType} - * @return - */ - public TaskGroup createTaskGroup(int type) { - - // ųע - - TaskGroup taskGroup = new TaskGroup(); - String namesrv = namesrvConf.getNamesrvAddr(); - if (null != namesrv && !"".equals(namesrv)) { - String[] addresses = namesrv.split(";"); - for (String address : addresses) { - if (!MixAll.isLocalAddr(address)) { - switch (type) { - case REG_BROKER: - taskGroup.addTask(address, createRegBrokerTask(address)); - break; - case REG_TOPIC: - taskGroup.addTask(address, createRegTopicTask(address)); - break; - case UNREG_BROKER: - taskGroup.addTask(address, createUnRegBrokerTask(address)); - break; - default: - // TODO - } - } - } - } - - return taskGroup; - } - - - public Exec createRegBrokerTask(final String address) { - return new Exec() { - - @Override - public void beforeExec() { - // TODO - } - - - @Override - public Result doExec(String[] brokerAddr) throws Exception { - RegisterBrokerRequestHeader regBrokerRequestHeader = new RegisterBrokerRequestHeader(); - regBrokerRequestHeader.setBrokerAddr(brokerAddr[0]); - RemotingCommand request = - RemotingCommand.createRequestCommand(REGISTER_BROKER_SINGLE_VALUE, regBrokerRequestHeader); - RemotingCommand response = - RemotingHelper.invokeSync(address, request, namesrvConf.getSyncTimeout()); - if (SUCCESS_VALUE == response.getCode()) { - // TODO - - return Result.SUCCESS; - } - else { - // record failure - log.error("register broker single fail. code" + response.getCode() + ",remark:" - + response.getRemark()); - return new Result(false, "code:" + response.getCode() + ",remark:" + response.getRemark()); - } - } - - }; - } - - - public Exec createRegTopicTask(final String address) { - return new Exec() { - - @Override - public void beforeExec() { - // TODO - - } - - - @Override - public Result doExec(String[] ts) throws Exception { - RegisterOrderTopicRequestHeader regOrderTopicRequestHeader = new RegisterOrderTopicRequestHeader(); - regOrderTopicRequestHeader.setTopic(ts[0]); - regOrderTopicRequestHeader.setOrderTopicString(ts[1]); - RemotingCommand request = - RemotingCommand.createRequestCommand(REGISTER_ORDER_TOPIC_SINGLE_VALUE, - regOrderTopicRequestHeader); - - RemotingCommand response = - RemotingHelper.invokeSync(address, request, namesrvConf.getSyncTimeout()); - if (SUCCESS_VALUE == response.getCode()) { - // TODO - - return Result.SUCCESS; - } - else { - // record failure - log.error("register order topic single fail. code" + response.getCode() + ",remark:" - + response.getRemark()); - return new Result(false, "code:" + response.getCode() + ",remark:" + response.getRemark()); - } - } - - }; - } - - - public Exec createUnRegBrokerTask(final String address) { - return new Exec() { - - @Override - public void beforeExec() { - // TODO - } - - - @Override - public Result doExec(String[] brokerName) throws Exception { - UnRegisterBrokerRequestHeader unRegisterBrokerRequestHeader = new UnRegisterBrokerRequestHeader(); - unRegisterBrokerRequestHeader.setBrokerName(brokerName[0]); - RemotingCommand request = - RemotingCommand.createRequestCommand(MQRequestCode.UNREGISTER_BROKER_SINGLE_VALUE, unRegisterBrokerRequestHeader); - RemotingCommand response = - RemotingHelper.invokeSync(address, request, namesrvConf.getSyncTimeout()); - if (SUCCESS_VALUE == response.getCode()) { - // TODO - - return Result.SUCCESS; - } - else { - // record failure - log.error("register broker single fail. code" + response.getCode() + ",remark:" - + response.getRemark()); - return new Result(false, "code:" + response.getCode() + ",remark:" + response.getRemark()); - } - } - - }; - } - - - public void shutdown() { - clientTaskGroupExecutor.shutdown(); - } -} diff --git a/rocketmq-namesrv/src/main/java/com/alibaba/rocketmq/namesrv/processor/DefaultRequestProcessor.java b/rocketmq-namesrv/src/main/java/com/alibaba/rocketmq/namesrv/processor/DefaultRequestProcessor.java new file mode 100644 index 00000000..59c173b3 --- /dev/null +++ b/rocketmq-namesrv/src/main/java/com/alibaba/rocketmq/namesrv/processor/DefaultRequestProcessor.java @@ -0,0 +1,410 @@ +/** + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.rocketmq.namesrv.processor; + +import io.netty.channel.ChannelHandlerContext; + +import java.util.concurrent.atomic.AtomicLong; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.alibaba.rocketmq.common.constant.LoggerName; +import com.alibaba.rocketmq.common.help.FAQUrl; +import com.alibaba.rocketmq.common.namesrv.NamesrvUtil; +import com.alibaba.rocketmq.common.namesrv.RegisterBrokerResult; +import com.alibaba.rocketmq.common.protocol.MQProtos.MQRequestCode; +import com.alibaba.rocketmq.common.protocol.MQProtos.MQResponseCode; +import com.alibaba.rocketmq.common.protocol.body.TopicConfigSerializeWrapper; +import com.alibaba.rocketmq.common.protocol.header.namesrv.DeleteKVConfigRequestHeader; +import com.alibaba.rocketmq.common.protocol.header.namesrv.DeleteTopicInNamesrvRequestHeader; +import com.alibaba.rocketmq.common.protocol.header.namesrv.GetKVConfigRequestHeader; +import com.alibaba.rocketmq.common.protocol.header.namesrv.GetKVConfigResponseHeader; +import com.alibaba.rocketmq.common.protocol.header.namesrv.GetKVListByNamespaceRequestHeader; +import com.alibaba.rocketmq.common.protocol.header.namesrv.GetRouteInfoRequestHeader; +import com.alibaba.rocketmq.common.protocol.header.namesrv.PutKVConfigRequestHeader; +import com.alibaba.rocketmq.common.protocol.header.namesrv.RegisterBrokerRequestHeader; +import com.alibaba.rocketmq.common.protocol.header.namesrv.RegisterBrokerResponseHeader; +import com.alibaba.rocketmq.common.protocol.header.namesrv.UnRegisterBrokerRequestHeader; +import com.alibaba.rocketmq.common.protocol.header.namesrv.WipeWritePermOfBrokerRequestHeader; +import com.alibaba.rocketmq.common.protocol.header.namesrv.WipeWritePermOfBrokerResponseHeader; +import com.alibaba.rocketmq.common.protocol.route.TopicRouteData; +import com.alibaba.rocketmq.namesrv.NamesrvController; +import com.alibaba.rocketmq.remoting.common.RemotingHelper; +import com.alibaba.rocketmq.remoting.exception.RemotingCommandException; +import com.alibaba.rocketmq.remoting.netty.NettyRequestProcessor; +import com.alibaba.rocketmq.remoting.protocol.RemotingCommand; +import com.alibaba.rocketmq.remoting.protocol.RemotingProtos.ResponseCode; + + +/** + * Name Server网络请求处理 + * + * @author shijia.wxr + * @since 2013-7-5 + */ +public class DefaultRequestProcessor implements NettyRequestProcessor { + private static final Logger log = LoggerFactory.getLogger(LoggerName.NamesrvLoggerName); + + private final NamesrvController namesrvController; + + + public DefaultRequestProcessor(NamesrvController namesrvController) { + this.namesrvController = namesrvController; + } + + + @Override + public RemotingCommand processRequest(ChannelHandlerContext ctx, RemotingCommand request) + throws RemotingCommandException { + MQRequestCode code = MQRequestCode.valueOf(request.getCode()); + if (log.isDebugEnabled()) { + log.debug("receive request, {} {} {}",// + code, // + RemotingHelper.parseChannelRemoteAddr(ctx.channel()), // + request); + } + + switch (code) { + case PUT_KV_CONFIG: + return this.putKVConfig(ctx, request); + case GET_KV_CONFIG: + return this.getKVConfig(ctx, request); + case DELETE_KV_CONFIG: + return this.deleteKVConfig(ctx, request); + case REGISTER_BROKER: + return this.registerBroker(ctx, request); + case UNREGISTER_BROKER: + return this.unregisterBroker(ctx, request); + case GET_ROUTEINTO_BY_TOPIC: + return this.getRouteInfoByTopic(ctx, request); + case GET_BROKER_CLUSTER_INFO: + return this.getBrokerClusterInfo(ctx, request); + case WIPE_WRITE_PERM_OF_BROKER: + return this.wipeWritePermOfBroker(ctx, request); + case GET_ALL_TOPIC_LIST_FROM_NAMESERVER: + return getAllTopicListFromNameserver(ctx, request); + case DELETE_TOPIC_IN_NAMESRV: + return deleteTopicInNamesrv(ctx, request); + case GET_KV_CONFIG_BY_VALUE: + return getKVConfigByValue(ctx, request); + case DELETE_KV_CONFIG_BY_VALUE: + return deleteKVConfigByValue(ctx, request); + case GET_KVLIST_BY_NAMESPACE: + return this.getKVListByNamespace(ctx, request); + default: + break; + } + return null; + } + + + /** + * 获取一个Namespace下的所有kv + */ + private RemotingCommand getKVListByNamespace(ChannelHandlerContext ctx, RemotingCommand request) + throws RemotingCommandException { + final RemotingCommand response = RemotingCommand.createResponseCommand(null); + final GetKVListByNamespaceRequestHeader requestHeader = + (GetKVListByNamespaceRequestHeader) request + .decodeCommandCustomHeader(GetKVListByNamespaceRequestHeader.class); + + byte[] jsonValue = this.namesrvController.getKvConfigManager().getKVListByNamespace(// + requestHeader.getNamespace()); + if (null != jsonValue) { + response.setBody(jsonValue); + response.setCode(ResponseCode.SUCCESS_VALUE); + response.setRemark(null); + return response; + } + + response.setCode(MQResponseCode.QUERY_NOT_FOUND_VALUE); + response.setRemark("No config item, Namespace: " + requestHeader.getNamespace()); + return response; + } + + + private RemotingCommand deleteTopicInNamesrv(ChannelHandlerContext ctx, RemotingCommand request) + throws RemotingCommandException { + final RemotingCommand response = RemotingCommand.createResponseCommand(null); + final DeleteTopicInNamesrvRequestHeader requestHeader = + (DeleteTopicInNamesrvRequestHeader) request + .decodeCommandCustomHeader(DeleteTopicInNamesrvRequestHeader.class); + + this.namesrvController.getRouteInfoManager().deleteTopic(requestHeader.getTopic()); + + response.setCode(ResponseCode.SUCCESS_VALUE); + response.setRemark(null); + return response; + } + + + /** + * 获取全部Topic列表 + * + * @param ctx + * @param request + * @return + */ + private RemotingCommand getAllTopicListFromNameserver(ChannelHandlerContext ctx, RemotingCommand request) { + final RemotingCommand response = RemotingCommand.createResponseCommand(null); + + byte[] body = this.namesrvController.getRouteInfoManager().getAllTopicList(); + + response.setBody(body); + response.setCode(ResponseCode.SUCCESS_VALUE); + response.setRemark(null); + return response; + } + + + private RemotingCommand wipeWritePermOfBroker(ChannelHandlerContext ctx, RemotingCommand request) + throws RemotingCommandException { + final RemotingCommand response = + RemotingCommand.createResponseCommand(WipeWritePermOfBrokerResponseHeader.class); + final WipeWritePermOfBrokerResponseHeader responseHeader = + (WipeWritePermOfBrokerResponseHeader) response.getCustomHeader(); + final WipeWritePermOfBrokerRequestHeader requestHeader = + (WipeWritePermOfBrokerRequestHeader) request + .decodeCommandCustomHeader(WipeWritePermOfBrokerRequestHeader.class); + + int wipeTopicCnt = + this.namesrvController.getRouteInfoManager().wipeWritePermOfBrokerByLock( + requestHeader.getBrokerName()); + + log.info("wipe write perm of broker[{}], client: {}, {}", // + requestHeader.getBrokerName(), // + RemotingHelper.parseChannelRemoteAddr(ctx.channel()), // + wipeTopicCnt); + + responseHeader.setWipeTopicCount(wipeTopicCnt); + response.setCode(ResponseCode.SUCCESS_VALUE); + response.setRemark(null); + return response; + } + + + private RemotingCommand getBrokerClusterInfo(ChannelHandlerContext ctx, RemotingCommand request) { + final RemotingCommand response = RemotingCommand.createResponseCommand(null); + + byte[] content = this.namesrvController.getRouteInfoManager().getAllClusterInfo(); + response.setBody(content); + + response.setCode(ResponseCode.SUCCESS_VALUE); + response.setRemark(null); + return response; + } + + + public RemotingCommand getRouteInfoByTopic(ChannelHandlerContext ctx, RemotingCommand request) + throws RemotingCommandException { + final RemotingCommand response = RemotingCommand.createResponseCommand(null); + final GetRouteInfoRequestHeader requestHeader = + (GetRouteInfoRequestHeader) request + .decodeCommandCustomHeader(GetRouteInfoRequestHeader.class); + + TopicRouteData topicRouteData = + this.namesrvController.getRouteInfoManager().pickupTopicRouteData(requestHeader.getTopic()); + + if (topicRouteData != null) { + String orderTopicConf = + this.namesrvController.getKvConfigManager().getKVConfig( + NamesrvUtil.NAMESPACE_ORDER_TOPIC_CONFIG, requestHeader.getTopic()); + topicRouteData.setOrderTopicConf(orderTopicConf); + + byte[] content = topicRouteData.encode(); + response.setBody(content); + response.setCode(ResponseCode.SUCCESS_VALUE); + response.setRemark(null); + return response; + } + + response.setCode(MQResponseCode.TOPIC_NOT_EXIST_VALUE); + response.setRemark("No topic route info in name server for the topic: " + requestHeader.getTopic() + + FAQUrl.suggestTodo(FAQUrl.APPLY_TOPIC_URL)); + return response; + } + + + public RemotingCommand putKVConfig(ChannelHandlerContext ctx, RemotingCommand request) + throws RemotingCommandException { + final RemotingCommand response = RemotingCommand.createResponseCommand(null); + final PutKVConfigRequestHeader requestHeader = + (PutKVConfigRequestHeader) request.decodeCommandCustomHeader(PutKVConfigRequestHeader.class); + + this.namesrvController.getKvConfigManager().putKVConfig(// + requestHeader.getNamespace(),// + requestHeader.getKey(),// + requestHeader.getValue()// + ); + + response.setCode(ResponseCode.SUCCESS_VALUE); + response.setRemark(null); + return response; + } + + + public RemotingCommand getKVConfig(ChannelHandlerContext ctx, RemotingCommand request) + throws RemotingCommandException { + final RemotingCommand response = + RemotingCommand.createResponseCommand(GetKVConfigResponseHeader.class); + final GetKVConfigResponseHeader responseHeader = + (GetKVConfigResponseHeader) response.getCustomHeader(); + final GetKVConfigRequestHeader requestHeader = + (GetKVConfigRequestHeader) request.decodeCommandCustomHeader(GetKVConfigRequestHeader.class); + + String value = this.namesrvController.getKvConfigManager().getKVConfig(// + requestHeader.getNamespace(),// + requestHeader.getKey()// + ); + + if (value != null) { + responseHeader.setValue(value); + response.setCode(ResponseCode.SUCCESS_VALUE); + response.setRemark(null); + return response; + } + + response.setCode(MQResponseCode.QUERY_NOT_FOUND_VALUE); + response.setRemark("No config item, Namespace: " + requestHeader.getNamespace() + " Key: " + + requestHeader.getKey()); + return response; + } + + + public RemotingCommand deleteKVConfig(ChannelHandlerContext ctx, RemotingCommand request) + throws RemotingCommandException { + final RemotingCommand response = RemotingCommand.createResponseCommand(null); + final DeleteKVConfigRequestHeader requestHeader = + (DeleteKVConfigRequestHeader) request + .decodeCommandCustomHeader(DeleteKVConfigRequestHeader.class); + + this.namesrvController.getKvConfigManager().deleteKVConfig(// + requestHeader.getNamespace(),// + requestHeader.getKey()// + ); + + response.setCode(ResponseCode.SUCCESS_VALUE); + response.setRemark(null); + return response; + } + + + public RemotingCommand registerBroker(ChannelHandlerContext ctx, RemotingCommand request) + throws RemotingCommandException { + final RemotingCommand response = + RemotingCommand.createResponseCommand(RegisterBrokerResponseHeader.class); + final RegisterBrokerResponseHeader responseHeader = + (RegisterBrokerResponseHeader) response.getCustomHeader(); + final RegisterBrokerRequestHeader requestHeader = + (RegisterBrokerRequestHeader) request + .decodeCommandCustomHeader(RegisterBrokerRequestHeader.class); + + TopicConfigSerializeWrapper topicConfigWrapper = null; + if (request.getBody() != null) { + topicConfigWrapper = + TopicConfigSerializeWrapper.decode(request.getBody(), TopicConfigSerializeWrapper.class); + } + else { + topicConfigWrapper = new TopicConfigSerializeWrapper(); + topicConfigWrapper.getDataVersion().setCounter(new AtomicLong(0)); + topicConfigWrapper.getDataVersion().setTimestatmp(0); + } + + RegisterBrokerResult result = this.namesrvController.getRouteInfoManager().registerBroker(// + requestHeader.getClusterName(), // 1 + requestHeader.getBrokerAddr(), // 2 + requestHeader.getBrokerName(), // 3 + requestHeader.getBrokerId(), // 4 + requestHeader.getHaServerAddr(),// 5 + topicConfigWrapper, // 6 + ctx.channel()// 7 + ); + + responseHeader.setHaServerAddr(result.getHaServerAddr()); + responseHeader.setMasterAddr(result.getMasterAddr()); + + response.setCode(ResponseCode.SUCCESS_VALUE); + response.setRemark(null); + return response; + } + + + public RemotingCommand unregisterBroker(ChannelHandlerContext ctx, RemotingCommand request) + throws RemotingCommandException { + final RemotingCommand response = RemotingCommand.createResponseCommand(null); + final UnRegisterBrokerRequestHeader requestHeader = + (UnRegisterBrokerRequestHeader) request + .decodeCommandCustomHeader(UnRegisterBrokerRequestHeader.class); + + this.namesrvController.getRouteInfoManager().unregisterBroker(// + requestHeader.getClusterName(), // 1 + requestHeader.getBrokerAddr(), // 2 + requestHeader.getBrokerName(), // 3 + requestHeader.getBrokerId()); + + response.setCode(ResponseCode.SUCCESS_VALUE); + response.setRemark(null); + return response; + } + + + public RemotingCommand getKVConfigByValue(ChannelHandlerContext ctx, RemotingCommand request) + throws RemotingCommandException { + final RemotingCommand response = + RemotingCommand.createResponseCommand(GetKVConfigResponseHeader.class); + final GetKVConfigResponseHeader responseHeader = + (GetKVConfigResponseHeader) response.getCustomHeader(); + final GetKVConfigRequestHeader requestHeader = + (GetKVConfigRequestHeader) request.decodeCommandCustomHeader(GetKVConfigRequestHeader.class); + + String value = this.namesrvController.getKvConfigManager().getKVConfigByValue(// + requestHeader.getNamespace(),// + requestHeader.getKey()// + ); + + if (value != null) { + responseHeader.setValue(value); + response.setCode(ResponseCode.SUCCESS_VALUE); + response.setRemark(null); + return response; + } + + response.setCode(MQResponseCode.QUERY_NOT_FOUND_VALUE); + response.setRemark("No config item, Namespace: " + requestHeader.getNamespace() + " Key: " + + requestHeader.getKey()); + return response; + } + + + public RemotingCommand deleteKVConfigByValue(ChannelHandlerContext ctx, RemotingCommand request) + throws RemotingCommandException { + final RemotingCommand response = RemotingCommand.createResponseCommand(null); + final DeleteKVConfigRequestHeader requestHeader = + (DeleteKVConfigRequestHeader) request + .decodeCommandCustomHeader(DeleteKVConfigRequestHeader.class); + + this.namesrvController.getKvConfigManager().deleteKVConfigByValue(// + requestHeader.getNamespace(),// + requestHeader.getKey()// + ); + + response.setCode(ResponseCode.SUCCESS_VALUE); + response.setRemark(null); + return response; + } + +} diff --git a/rocketmq-namesrv/src/main/java/com/alibaba/rocketmq/namesrv/routeinfo/BrokerHousekeepingService.java b/rocketmq-namesrv/src/main/java/com/alibaba/rocketmq/namesrv/routeinfo/BrokerHousekeepingService.java new file mode 100644 index 00000000..94b4fc88 --- /dev/null +++ b/rocketmq-namesrv/src/main/java/com/alibaba/rocketmq/namesrv/routeinfo/BrokerHousekeepingService.java @@ -0,0 +1,63 @@ +/** + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.rocketmq.namesrv.routeinfo; + +import io.netty.channel.Channel; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.alibaba.rocketmq.common.constant.LoggerName; +import com.alibaba.rocketmq.namesrv.NamesrvController; +import com.alibaba.rocketmq.remoting.ChannelEventListener; + + +/** + * @author shijia.wxr + * @since 2013-7-15 + */ +public class BrokerHousekeepingService implements ChannelEventListener { + private static final Logger log = LoggerFactory.getLogger(LoggerName.NamesrvLoggerName); + private final NamesrvController namesrvController; + + + public BrokerHousekeepingService(NamesrvController namesrvController) { + this.namesrvController = namesrvController; + } + + + @Override + public void onChannelConnect(String remoteAddr, Channel channel) { + } + + + @Override + public void onChannelClose(String remoteAddr, Channel channel) { + this.namesrvController.getRouteInfoManager().onChannelDestroy(remoteAddr, channel); + } + + + @Override + public void onChannelException(String remoteAddr, Channel channel) { + this.namesrvController.getRouteInfoManager().onChannelDestroy(remoteAddr, channel); + } + + + @Override + public void onChannelIdle(String remoteAddr, Channel channel) { + this.namesrvController.getRouteInfoManager().onChannelDestroy(remoteAddr, channel); + } +} diff --git a/rocketmq-namesrv/src/main/java/com/alibaba/rocketmq/namesrv/routeinfo/RouteInfoManager.java b/rocketmq-namesrv/src/main/java/com/alibaba/rocketmq/namesrv/routeinfo/RouteInfoManager.java new file mode 100644 index 00000000..2260870a --- /dev/null +++ b/rocketmq-namesrv/src/main/java/com/alibaba/rocketmq/namesrv/routeinfo/RouteInfoManager.java @@ -0,0 +1,697 @@ +/** + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.rocketmq.namesrv.routeinfo; + +import io.netty.channel.Channel; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Map.Entry; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.locks.ReadWriteLock; +import java.util.concurrent.locks.ReentrantReadWriteLock; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.alibaba.rocketmq.common.DataVersion; +import com.alibaba.rocketmq.common.MixAll; +import com.alibaba.rocketmq.common.TopicConfig; +import com.alibaba.rocketmq.common.constant.LoggerName; +import com.alibaba.rocketmq.common.constant.PermName; +import com.alibaba.rocketmq.common.namesrv.RegisterBrokerResult; +import com.alibaba.rocketmq.common.protocol.body.ClusterInfo; +import com.alibaba.rocketmq.common.protocol.body.TopicConfigSerializeWrapper; +import com.alibaba.rocketmq.common.protocol.body.TopicList; +import com.alibaba.rocketmq.common.protocol.route.BrokerData; +import com.alibaba.rocketmq.common.protocol.route.QueueData; +import com.alibaba.rocketmq.common.protocol.route.TopicRouteData; +import com.alibaba.rocketmq.remoting.common.RemotingUtil; + + +/** + * 运行过程中的路由信息,数据只在内存,宕机后数据消失,但是Broker会定期推送最新数据 + * + * @author shijia.wxr + * @since 2013-7-2 + */ +public class RouteInfoManager { + private static final Logger log = LoggerFactory.getLogger(LoggerName.NamesrvLoggerName); + private final ReadWriteLock lock = new ReentrantReadWriteLock(); + private final HashMap> topicQueueTable; + private final HashMap brokerAddrTable; + private final HashMap> clusterAddrTable; + private final HashMap brokerLiveTable; + + + public RouteInfoManager() { + this.topicQueueTable = new HashMap>(1024); + this.brokerAddrTable = new HashMap(128); + this.clusterAddrTable = new HashMap>(32); + this.brokerLiveTable = new HashMap(256); + } + + + public byte[] getAllClusterInfo() { + ClusterInfo clusterInfoSerializeWrapper = new ClusterInfo(); + clusterInfoSerializeWrapper.setBrokerAddrTable(this.brokerAddrTable); + clusterInfoSerializeWrapper.setClusterAddrTable(this.clusterAddrTable); + return clusterInfoSerializeWrapper.encode(); + } + + + public void deleteTopic(final String topic) { + try { + try { + this.lock.writeLock().lockInterruptibly(); + this.topicQueueTable.remove(topic); + } + finally { + this.lock.writeLock().unlock(); + } + } + catch (Exception e) { + log.error("deleteTopic Exception", e); + } + } + + + public byte[] getAllTopicList() { + TopicList topicList = new TopicList(); + try { + try { + this.lock.readLock().lockInterruptibly(); + topicList.getTopicList().addAll(this.topicQueueTable.keySet()); + } + finally { + this.lock.readLock().unlock(); + } + } + catch (Exception e) { + log.error("getAllTopicList Exception", e); + } + + return topicList.encode(); + } + + + /** + * @return 如果是slave,则返回master的ha地址 + */ + public RegisterBrokerResult registerBroker(// + final String clusterName,// 1 + final String brokerAddr,// 2 + final String brokerName,// 3 + final long brokerId,// 4 + final String haServerAddr,// 5 + final TopicConfigSerializeWrapper topicConfigWrapper,// 6 + final Channel channel// 7 + ) { + RegisterBrokerResult result = new RegisterBrokerResult(); + try { + try { + this.lock.writeLock().lockInterruptibly(); + + // 更新集群信息 + Set brokerNames = this.clusterAddrTable.get(clusterName); + if (null == brokerNames) { + brokerNames = new HashSet(); + this.clusterAddrTable.put(clusterName, brokerNames); + } + brokerNames.add(brokerName); + + boolean registerFirst = false; + + // 更新主备信息 + BrokerData brokerData = this.brokerAddrTable.get(brokerName); + if (null == brokerData) { + registerFirst = true; + brokerData = new BrokerData(); + brokerData.setBrokerName(brokerName); + HashMap brokerAddrs = new HashMap(); + brokerData.setBrokerAddrs(brokerAddrs); + + this.brokerAddrTable.put(brokerName, brokerData); + } + String oldAddr = brokerData.getBrokerAddrs().put(brokerId, brokerAddr); + registerFirst = registerFirst || (null == oldAddr); + + // 更新Topic信息 + if (null != topicConfigWrapper // + && MixAll.MASTER_ID == brokerId) { + if (this.isBrokerTopicConfigChanged(brokerAddr, topicConfigWrapper.getDataVersion())// + || registerFirst) { + ConcurrentHashMap tcTable = + topicConfigWrapper.getTopicConfigTable(); + if (tcTable != null) { + for (String topic : tcTable.keySet()) { + TopicConfig topicConfig = tcTable.get(topic); + this.createAndUpdateQueueData(brokerName, topicConfig); + } + } + } + } + + // 更新最后变更时间 + BrokerLiveInfo prevBrokerLiveInfo = this.brokerLiveTable.put(brokerAddr, // + new BrokerLiveInfo(// + System.currentTimeMillis(), // + topicConfigWrapper.getDataVersion(),// + channel, // + haServerAddr)); + if (null == prevBrokerLiveInfo) { + log.info("new broker registerd, {} HAServer: {}", brokerAddr, haServerAddr); + } + + // 返回值 + if (MixAll.MASTER_ID != brokerId) { + String masterAddr = brokerData.getBrokerAddrs().get(MixAll.MASTER_ID); + if (masterAddr != null) { + BrokerLiveInfo brokerLiveInfo = this.brokerLiveTable.get(masterAddr); + if (brokerLiveInfo != null) { + result.setHaServerAddr(brokerLiveInfo.getHaServerAddr()); + result.setMasterAddr(masterAddr); + } + } + } + } + finally { + this.lock.writeLock().unlock(); + } + } + catch (Exception e) { + log.error("registerBroker Exception", e); + } + + return result; + } + + + /** + * 判断Topic配置信息是否发生变更 + */ + private boolean isBrokerTopicConfigChanged(final String brokerAddr, final DataVersion dataVersion) { + BrokerLiveInfo prev = this.brokerLiveTable.get(brokerAddr); + if (null == prev || !prev.getDataVersion().equals(dataVersion)) { + return true; + } + + return false; + } + + + public int wipeWritePermOfBrokerByLock(final String brokerName) { + try { + try { + this.lock.writeLock().lockInterruptibly(); + return wipeWritePermOfBroker(brokerName); + } + finally { + this.lock.writeLock().unlock(); + } + } + catch (Exception e) { + log.error("wipeWritePermOfBrokerByLock Exception", e); + } + + return 0; + } + + + private int wipeWritePermOfBroker(final String brokerName) { + int wipeTopicCnt = 0; + Iterator>> itTopic = this.topicQueueTable.entrySet().iterator(); + while (itTopic.hasNext()) { + Entry> entry = itTopic.next(); + List qdList = entry.getValue(); + + Iterator it = qdList.iterator(); + while (it.hasNext()) { + QueueData qd = it.next(); + if (qd.getBrokerName().equals(brokerName)) { + int perm = qd.getPerm(); + perm &= ~PermName.PERM_WRITE; + qd.setPerm(perm); + wipeTopicCnt++; + } + } + } + + return wipeTopicCnt; + } + + + private void createAndUpdateQueueData(final String brokerName, final TopicConfig topicConfig) { + QueueData queueData = new QueueData(); + queueData.setBrokerName(brokerName); + queueData.setWriteQueueNums(topicConfig.getWriteQueueNums()); + queueData.setReadQueueNums(topicConfig.getReadQueueNums()); + queueData.setPerm(topicConfig.getPerm()); + + List queueDataList = this.topicQueueTable.get(topicConfig.getTopicName()); + if (null == queueDataList) { + queueDataList = new LinkedList(); + queueDataList.add(queueData); + this.topicQueueTable.put(topicConfig.getTopicName(), queueDataList); + log.info("new topic registerd, {} {}", topicConfig.getTopicName(), queueData); + } + else { + boolean addNewOne = true; + + Iterator it = queueDataList.iterator(); + while (it.hasNext()) { + QueueData qd = it.next(); + if (qd.getBrokerName().equals(brokerName)) { + if (qd.equals(queueData)) { + addNewOne = false; + } + else { + log.info("topic changed, {} OLD: {} NEW: {}", topicConfig.getTopicName(), qd, + queueData); + it.remove(); + } + } + } + + if (addNewOne) { + queueDataList.add(queueData); + } + } + } + + + public void unregisterBroker(// + final String clusterName,// 1 + final String brokerAddr,// 2 + final String brokerName,// 3 + final long brokerId// 4 + ) { + try { + try { + this.lock.writeLock().lockInterruptibly(); + BrokerLiveInfo brokerLiveInfo = this.brokerLiveTable.remove(brokerAddr); + if (brokerLiveInfo != null) { + log.info("unregisterBroker, remove from brokerLiveTable {}, {}", // + (brokerLiveInfo != null ? "OK" : "Failed"),// + brokerAddr// + ); + } + + boolean removeBrokerName = false; + BrokerData brokerData = this.brokerAddrTable.get(brokerName); + if (null != brokerData) { + String addr = brokerData.getBrokerAddrs().remove(brokerId); + log.info("unregisterBroker, remove addr from brokerAddrTable {}, {}", // + (addr != null ? "OK" : "Failed"),// + brokerAddr// + ); + + if (brokerData.getBrokerAddrs().isEmpty()) { + this.brokerAddrTable.remove(brokerName); + log.info("unregisterBroker, remove name from brokerAddrTable OK, {}", // + brokerName// + ); + + removeBrokerName = true; + } + } + + if (removeBrokerName) { + Set nameSet = this.clusterAddrTable.get(clusterName); + if (nameSet != null) { + boolean removed = nameSet.remove(brokerName); + log.info("unregisterBroker, remove name from clusterAddrTable {}, {}", // + (removed ? "OK" : "Failed"),// + brokerName// + ); + + if (nameSet.isEmpty()) { + this.clusterAddrTable.remove(clusterName); + log.info("unregisterBroker, remove cluster from clusterAddrTable {}", // + clusterName// + ); + } + } + + // 删除相应的topic + this.removeTopicByBrokerName(brokerName); + } + } + finally { + this.lock.writeLock().unlock(); + } + } + catch (Exception e) { + log.error("unregisterBroker Exception", e); + } + } + + + private void removeTopicByBrokerName(final String brokerName) { + Iterator>> itMap = this.topicQueueTable.entrySet().iterator(); + while (itMap.hasNext()) { + Entry> entry = itMap.next(); + + String topic = entry.getKey(); + List queueDataList = entry.getValue(); + Iterator it = queueDataList.iterator(); + while (it.hasNext()) { + QueueData qd = it.next(); + if (qd.getBrokerName().equals(brokerName)) { + log.info("removeTopicByBrokerName, remove one broker's topic {} {}", topic, qd); + it.remove(); + } + } + + if (queueDataList.isEmpty()) { + log.info("removeTopicByBrokerName, remove the topic all queue {}", topic); + itMap.remove(); + } + } + } + + + public TopicRouteData pickupTopicRouteData(final String topic) { + TopicRouteData topicRouteData = new TopicRouteData(); + boolean foundQueueData = false; + boolean foundBrokerData = false; + Set brokerNameSet = new HashSet(); + List brokerDataList = new LinkedList(); + topicRouteData.setBrokerDatas(brokerDataList); + + try { + try { + this.lock.readLock().lockInterruptibly(); + List queueDataList = this.topicQueueTable.get(topic); + if (queueDataList != null) { + topicRouteData.setQueueDatas(queueDataList); + foundQueueData = true; + + // BrokerName去重 + Iterator it = queueDataList.iterator(); + while (it.hasNext()) { + QueueData qd = it.next(); + brokerNameSet.add(qd.getBrokerName()); + } + + for (String brokerName : brokerNameSet) { + BrokerData brokerData = this.brokerAddrTable.get(brokerName); + if (null != brokerData) { + BrokerData brokerDataClone = new BrokerData(); + brokerDataClone.setBrokerName(brokerData.getBrokerName()); + brokerDataClone.setBrokerAddrs((HashMap) brokerData + .getBrokerAddrs().clone()); + brokerDataList.add(brokerDataClone); + foundBrokerData = true; + } + } + } + } + finally { + this.lock.readLock().unlock(); + } + } + catch (Exception e) { + log.error("pickupTopicRouteData Exception", e); + } + + if (log.isDebugEnabled()) { + log.debug("pickupTopicRouteData {} {}", topic, topicRouteData); + } + + if (foundBrokerData && foundQueueData) { + return topicRouteData; + } + + return null; + } + + // Broker Channel两分钟过期 + private final static long BrokerChannelExpiredTime = 1000 * 60 * 2; + + + public void scanNotActiveBroker() { + Iterator> it = this.brokerLiveTable.entrySet().iterator(); + while (it.hasNext()) { + Entry next = it.next(); + long last = next.getValue().getLastUpdateTimestamp(); + if ((last + BrokerChannelExpiredTime) < System.currentTimeMillis()) { + RemotingUtil.closeChannel(next.getValue().getChannel()); + it.remove(); + log.warn("The broker channel expired, {} {}ms", next.getKey(), BrokerChannelExpiredTime); + this.onChannelDestroy(next.getKey(), next.getValue().getChannel()); + } + } + } + + + /** + * Channel被关闭,或者Channel Idle时间超限 + */ + public void onChannelDestroy(String remoteAddr, Channel channel) { + String brokerAddrFound = null; + + // 加读锁,寻找断开连接的Broker + if (channel != null) { + try { + try { + this.lock.readLock().lockInterruptibly(); + Iterator> itBrokerLiveTable = + this.brokerLiveTable.entrySet().iterator(); + while (itBrokerLiveTable.hasNext()) { + Entry entry = itBrokerLiveTable.next(); + if (entry.getValue().getChannel() == channel) { + brokerAddrFound = entry.getKey(); + break; + } + } + } + finally { + this.lock.readLock().unlock(); + } + } + catch (Exception e) { + log.error("onChannelDestroy Exception", e); + } + } + + if (null == brokerAddrFound) { + brokerAddrFound = remoteAddr; + } + + // 加写锁,删除相关数据结构 + if (brokerAddrFound != null && brokerAddrFound.length() > 0) { + log.info("the broker's channel destroyed, {}, clean it's data structure at once", brokerAddrFound); + + try { + try { + this.lock.writeLock().lockInterruptibly(); + // 清理brokerLiveTable + this.brokerLiveTable.remove(brokerAddrFound); + + // 清理brokerAddrTable + String brokerNameFound = null; + boolean removeBrokerName = false; + Iterator> itBrokerAddrTable = + this.brokerAddrTable.entrySet().iterator(); + while (itBrokerAddrTable.hasNext() && (null == brokerNameFound)) { + BrokerData brokerData = itBrokerAddrTable.next().getValue(); + + // 遍历Master/Slave,删除brokerAddr + Iterator> it = brokerData.getBrokerAddrs().entrySet().iterator(); + while (it.hasNext()) { + Entry entry = it.next(); + Long brokerId = entry.getKey(); + String brokerAddr = entry.getValue(); + if (brokerAddr.equals(brokerAddrFound)) { + brokerNameFound = brokerData.getBrokerName(); + it.remove(); + log.info( + "remove brokerAddr[{}, {}] from brokerAddrTable, because channel destroyed", + brokerId, brokerAddr); + break; + } + } + + // BrokerName无关联BrokerAddr + if (brokerData.getBrokerAddrs().isEmpty()) { + removeBrokerName = true; + itBrokerAddrTable.remove(); + log.info("remove brokerName[{}] from brokerAddrTable, because channel destroyed", + brokerData.getBrokerName()); + } + } + + // 清理clusterAddrTable + if (brokerNameFound != null && removeBrokerName) { + Iterator>> it = this.clusterAddrTable.entrySet().iterator(); + while (it.hasNext()) { + Entry> entry = it.next(); + String clusterName = entry.getKey(); + Set brokerNames = entry.getValue(); + boolean removed = brokerNames.remove(brokerNameFound); + if (removed) { + log.info( + "remove brokerName[{}], clusterName[{}] from clusterAddrTable, because channel destroyed", + brokerNameFound, clusterName); + + // 如果集群对应的所有broker都下线了, 则集群也删除掉 + if (brokerNames.isEmpty()) { + log.info( + "remove the clusterName[{}] from clusterAddrTable, because channel destroyed and no broker in this cluster", + clusterName); + it.remove(); + } + + break; + } + } + } + + // 清理topicQueueTable + if (removeBrokerName) { + Iterator>> itTopicQueueTable = + this.topicQueueTable.entrySet().iterator(); + while (itTopicQueueTable.hasNext()) { + Entry> entry = itTopicQueueTable.next(); + String topic = entry.getKey(); + List queueDataList = entry.getValue(); + + Iterator itQueueData = queueDataList.iterator(); + while (itQueueData.hasNext()) { + QueueData queueData = itQueueData.next(); + if (queueData.getBrokerName().equals(brokerNameFound)) { + itQueueData.remove(); + log.info( + "remove topic[{} {}], from topicQueueTable, because channel destroyed", + topic, queueData); + } + } + + if (queueDataList.isEmpty()) { + itTopicQueueTable.remove(); + log.info( + "remove topic[{}] all queue, from topicQueueTable, because channel destroyed", + topic); + } + } + } + } + finally { + this.lock.writeLock().unlock(); + } + } + catch (Exception e) { + log.error("onChannelDestroy Exception", e); + } + } + } + + + /** + * 定期打印当前类的数据结构 + */ + public void printAllPeriodically() { + try { + try { + this.lock.readLock().lockInterruptibly(); + log.info("--------------------------------------------------------"); + + log.info("topicQueueTable {}", this.topicQueueTable); + + log.info("brokerAddrTable {}", this.brokerAddrTable); + + log.info("brokerLiveTable {}", this.brokerLiveTable); + + log.info("clusterAddrTable {}", this.clusterAddrTable); + } + finally { + this.lock.readLock().unlock(); + } + } + catch (Exception e) { + log.error("printAllPeriodically Exception", e); + } + } +} + + +class BrokerLiveInfo { + private long lastUpdateTimestamp; + private DataVersion dataVersion; + private Channel channel; + private String haServerAddr; + + + public BrokerLiveInfo(long lastUpdateTimestamp, DataVersion dataVersion, Channel channel, + String haServerAddr) { + this.lastUpdateTimestamp = lastUpdateTimestamp; + this.dataVersion = dataVersion; + this.channel = channel; + this.haServerAddr = haServerAddr; + } + + + public long getLastUpdateTimestamp() { + return lastUpdateTimestamp; + } + + + public void setLastUpdateTimestamp(long lastUpdateTimestamp) { + this.lastUpdateTimestamp = lastUpdateTimestamp; + } + + + public DataVersion getDataVersion() { + return dataVersion; + } + + + public void setDataVersion(DataVersion dataVersion) { + this.dataVersion = dataVersion; + } + + + public Channel getChannel() { + return channel; + } + + + public void setChannel(Channel channel) { + this.channel = channel; + } + + + public String getHaServerAddr() { + return haServerAddr; + } + + + public void setHaServerAddr(String haServerAddr) { + this.haServerAddr = haServerAddr; + } + + + @Override + public String toString() { + return "BrokerLiveInfo [lastUpdateTimestamp=" + lastUpdateTimestamp + ", dataVersion=" + dataVersion + + ", channel=" + channel + ", haServerAddr=" + haServerAddr + "]"; + } +} diff --git a/rocketmq-namesrv/src/main/java/com/alibaba/rocketmq/namesrv/sync/Exec.java b/rocketmq-namesrv/src/main/java/com/alibaba/rocketmq/namesrv/sync/Exec.java deleted file mode 100644 index c0542772..00000000 --- a/rocketmq-namesrv/src/main/java/com/alibaba/rocketmq/namesrv/sync/Exec.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.alibaba.rocketmq.namesrv.sync; - -/** - * - * @author lansheng.zj@taobao.com - * - * @param ֵ - * @param - */ -public abstract class Exec { - - public void beforeExec(){} - - public abstract R doExec(T param) throws Exception; - - public void afterExec(R r){} - - public R exec(T param) throws Exception { - beforeExec(); - R r = doExec(param); - afterExec(r); - return r; - } - - -} diff --git a/rocketmq-namesrv/src/main/java/com/alibaba/rocketmq/namesrv/sync/FutureGroup.java b/rocketmq-namesrv/src/main/java/com/alibaba/rocketmq/namesrv/sync/FutureGroup.java deleted file mode 100644 index a76cfa0e..00000000 --- a/rocketmq-namesrv/src/main/java/com/alibaba/rocketmq/namesrv/sync/FutureGroup.java +++ /dev/null @@ -1,85 +0,0 @@ -package com.alibaba.rocketmq.namesrv.sync; - -import static com.alibaba.rocketmq.common.MixAll.Localhost; -import static com.alibaba.rocketmq.namesrv.common.Result.SUCCESS; - -import java.util.HashMap; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.Future; -import java.util.concurrent.TimeUnit; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.alibaba.rocketmq.common.MixAll; -import com.alibaba.rocketmq.namesrv.common.Result; - - -/** - * - * @author lansheng.zj@taobao.com - * - * @param - * ֵ - * - */ -public class FutureGroup { - - private static final Logger log = LoggerFactory.getLogger(MixAll.NamesrvLoggerName); - private CountDownLatch latch; - private Map> resultMap; - private Set keys; - - - public FutureGroup(CountDownLatch latch, Set keys) { - this.latch = latch; - this.keys = keys; - resultMap = new HashMap>(); - } - - - public void addResult(String key, Future r) { - resultMap.put(key, r); - } - - - public Result await(long timeout) { - try { - if (latch.await(timeout, TimeUnit.MILLISECONDS)) - return SUCCESS; - else - return new Result(false, detailInfo()); - } - catch (Exception e) { - log.error("FutureGroup await error.", e); - return new Result(false, Localhost + " system error " + e.getMessage()); - } - } - - - public Set getKeys() { - return keys; - } - - - public void setKeys(Set keys) { - this.keys = keys; - } - - - public Map> getResultMap() { - return resultMap; - } - - - public String detailInfo() { - StringBuilder info = new StringBuilder(); - for (String key : keys) { - info.append(key).append(":").append(resultMap.get(key)).append("\n"); - } - - return info.toString(); - } -} diff --git a/rocketmq-namesrv/src/main/java/com/alibaba/rocketmq/namesrv/sync/Task.java b/rocketmq-namesrv/src/main/java/com/alibaba/rocketmq/namesrv/sync/Task.java deleted file mode 100644 index 7623dbe8..00000000 --- a/rocketmq-namesrv/src/main/java/com/alibaba/rocketmq/namesrv/sync/Task.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.alibaba.rocketmq.namesrv.sync; - -/** - * @author lansheng.zj@taobao.com - * - * @param ֵ - * @param - */ -public class Task { - - private Exec call; - - - public Task(Exec call) { - this.call = call; - } - - - public V exec(T t) throws Exception { - return call.exec(t); - } -} diff --git a/rocketmq-namesrv/src/main/java/com/alibaba/rocketmq/namesrv/sync/TaskGroup.java b/rocketmq-namesrv/src/main/java/com/alibaba/rocketmq/namesrv/sync/TaskGroup.java deleted file mode 100644 index d853295c..00000000 --- a/rocketmq-namesrv/src/main/java/com/alibaba/rocketmq/namesrv/sync/TaskGroup.java +++ /dev/null @@ -1,77 +0,0 @@ -package com.alibaba.rocketmq.namesrv.sync; - -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; - - -/** - * - * @author lansheng.zj@taobao.com - * - * @param ֵ - * @param - */ -public class TaskGroup implements Iterable>> { - - private Map> taskMap; - - - public TaskGroup() { - this.taskMap = new HashMap>(); - } - - - public Task addTask(String key, Exec task) { - return taskMap.put(key, new Task(task)); - } - - - public Task getTask(String key) { - return taskMap.get(key); - } - - - public Task removeTask(String key) { - return taskMap.remove(key); - } - - - public int size() { - return taskMap.size(); - } - - - public Set getKeys() { - return taskMap.keySet(); - } - - - @Override - public Iterator>> iterator() { - return new Iterator>>() { - - private Iterator>> iterator = taskMap.entrySet().iterator(); - - - @Override - public boolean hasNext() { - return iterator.hasNext(); - } - - - @Override - public Entry> next() { - return iterator.next(); - } - - - @Override - public void remove() { - iterator.remove(); - } - }; - } -} diff --git a/rocketmq-namesrv/src/main/java/com/alibaba/rocketmq/namesrv/sync/TaskGroupExecutor.java b/rocketmq-namesrv/src/main/java/com/alibaba/rocketmq/namesrv/sync/TaskGroupExecutor.java deleted file mode 100644 index d3fcd351..00000000 --- a/rocketmq-namesrv/src/main/java/com/alibaba/rocketmq/namesrv/sync/TaskGroupExecutor.java +++ /dev/null @@ -1,82 +0,0 @@ -package com.alibaba.rocketmq.namesrv.sync; - -import java.util.Map.Entry; -import java.util.concurrent.Callable; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.ThreadFactory; -import java.util.concurrent.atomic.AtomicInteger; - - -/** - * @author lansheng.zj@taobao.com - * - * @param - * ֵ - * @param - * - */ -public class TaskGroupExecutor { - private ExecutorService executorService; - - - public TaskGroupExecutor(ThreadFactory threadFactory) { - this(32, threadFactory); - } - - - public TaskGroupExecutor(int nThreads, ThreadFactory threadFactory) { - executorService = Executors.newFixedThreadPool(nThreads, threadFactory); - } - - - public TaskGroupExecutor(int nThreads) { - executorService = Executors.newFixedThreadPool(nThreads, new ThreadFactory() { - - private AtomicInteger index = new AtomicInteger(0); - - - @Override - public Thread newThread(Runnable r) { - return new Thread(r, "taskgroup-executor-" + index.getAndIncrement()); - } - }); - } - - - public FutureGroup groupCommit(TaskGroup taskGroup, final T t) { - final CountDownLatch latch = new CountDownLatch(taskGroup.size()); - FutureGroup future = new FutureGroup(latch, taskGroup.getKeys()); - - for (final Entry> entry : taskGroup) { - future.addResult(entry.getKey(), executorService.submit(new Callable() { - - @Override - public R call() throws Exception { - - try { - return entry.getValue().exec(t); - } - catch (Exception e) { - // TODO - - throw e; - } - finally { - latch.countDown(); - } - } - - })); - } - - return future; - } - - - public void shutdown() { - executorService.shutdown(); - } - -} diff --git a/rocketmq-namesrv/src/main/java/com/alibaba/rocketmq/namesrv/sync/TaskType.java b/rocketmq-namesrv/src/main/java/com/alibaba/rocketmq/namesrv/sync/TaskType.java deleted file mode 100644 index 55c500d4..00000000 --- a/rocketmq-namesrv/src/main/java/com/alibaba/rocketmq/namesrv/sync/TaskType.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.alibaba.rocketmq.namesrv.sync; - -/** - * - * - * @author lansheng.zj@taobao.com - */ -public abstract class TaskType { - - /** - * עbroker - */ - public static final int REG_BROKER = 1; - - /** - * עtopic - */ - public static final int REG_TOPIC = 2; - - /** - * עbroker - */ - public static final int UNREG_BROKER = 3; - -} diff --git a/rocketmq-namesrv/src/main/java/com/alibaba/rocketmq/namesrv/topic/DefaultNamesrvConfigManager.java b/rocketmq-namesrv/src/main/java/com/alibaba/rocketmq/namesrv/topic/DefaultNamesrvConfigManager.java deleted file mode 100644 index 4f68be75..00000000 --- a/rocketmq-namesrv/src/main/java/com/alibaba/rocketmq/namesrv/topic/DefaultNamesrvConfigManager.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.alibaba.rocketmq.namesrv.topic; - -import com.alibaba.rocketmq.common.namesrv.NamesrvConfig; - - -/** - * @auther lansheng.zj@taobao.com - */ -public class DefaultNamesrvConfigManager implements NamesrvConfigManager{ - - private NamesrvConfig namesrvConfig; - - - public DefaultNamesrvConfigManager(NamesrvConfig nConfig) { - namesrvConfig = nConfig; - } - -} diff --git a/rocketmq-namesrv/src/main/java/com/alibaba/rocketmq/namesrv/topic/DefaultTopicRuntimeDataManager.java b/rocketmq-namesrv/src/main/java/com/alibaba/rocketmq/namesrv/topic/DefaultTopicRuntimeDataManager.java deleted file mode 100644 index 1fe19715..00000000 --- a/rocketmq-namesrv/src/main/java/com/alibaba/rocketmq/namesrv/topic/DefaultTopicRuntimeDataManager.java +++ /dev/null @@ -1,723 +0,0 @@ -package com.alibaba.rocketmq.namesrv.topic; - -import static com.alibaba.rocketmq.common.MixAll.Localhost; -import static com.alibaba.rocketmq.common.namesrv.TopicRuntimeData.ORDER_PREFIX; -import static com.alibaba.rocketmq.common.protocol.MQProtos.MQResponseCode.REGISTER_BROKER_FAIL_VALUE; -import static com.alibaba.rocketmq.common.protocol.MQProtos.MQResponseCode.REGISTER_BROKER_TIMEOUT_VALUE; -import static com.alibaba.rocketmq.common.protocol.MQProtos.MQResponseCode.REGISTER_ORDER_TOPIC_FAIL_VALUE; -import static com.alibaba.rocketmq.common.protocol.MQProtos.MQResponseCode.REGISTER_ORDER_TOPIC_TIMEOUT_VALUE; -import static com.alibaba.rocketmq.common.protocol.MQProtos.MQResponseCode.TOPIC_NOT_EXIST_VALUE; -import static com.alibaba.rocketmq.common.protocol.MQProtos.MQResponseCode.UNREGISTER_BROKER_FAIL_VALUE; -import static com.alibaba.rocketmq.common.protocol.MQProtos.MQResponseCode.UNREGISTER_BROKER_TIMEOUT_VALUE; -import static com.alibaba.rocketmq.namesrv.common.MergeResult.MERGE_INVALID; -import static com.alibaba.rocketmq.namesrv.common.MergeResult.NOT_MERGE; -import static com.alibaba.rocketmq.namesrv.common.MergeResult.SYS_ERROR; -import static com.alibaba.rocketmq.namesrv.sync.TaskType.REG_BROKER; -import static com.alibaba.rocketmq.namesrv.sync.TaskType.REG_TOPIC; -import static com.alibaba.rocketmq.namesrv.sync.TaskType.UNREG_BROKER; -import static com.alibaba.rocketmq.remoting.protocol.RemotingProtos.ResponseCode.SUCCESS_VALUE; - -import java.beans.PropertyChangeListener; -import java.io.File; -import java.io.FileInputStream; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Properties; -import java.util.concurrent.Future; -import java.util.concurrent.locks.ReentrantReadWriteLock; -import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock; -import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.alibaba.rocketmq.common.MixAll; -import com.alibaba.rocketmq.common.protocol.MQProtos.MQResponseCode; -import com.alibaba.rocketmq.common.protocol.route.ObjectConverter; -import com.alibaba.rocketmq.common.namesrv.NamesrvConfig; -import com.alibaba.rocketmq.common.namesrv.TopicRuntimeData; -import com.alibaba.rocketmq.common.protocol.route.BrokerData; -import com.alibaba.rocketmq.common.protocol.route.QueueData; -import com.alibaba.rocketmq.common.protocol.route.TopicRouteData; -import com.alibaba.rocketmq.namesrv.common.MergeResultHolder; -import com.alibaba.rocketmq.namesrv.common.Result; -import com.alibaba.rocketmq.namesrv.processor.ChangeSpreadProcessor; -import com.alibaba.rocketmq.namesrv.sync.FutureGroup; -import com.alibaba.rocketmq.remoting.protocol.RemotingCommand; - - -/** - * @author lansheng.zj@taobao.com - */ -public class DefaultTopicRuntimeDataManager implements TopicRuntimeDataManager { - - private static final Logger log = LoggerFactory.getLogger(MixAll.NamesrvLoggerName); - - private NamesrvConfig namesrvConfig; - private TopicRuntimeData topicData; - private ChangeSpreadProcessor changeSpread; - private ReentrantReadWriteLock lock; - private ReadLock readLock; - private WriteLock writeLock; - - - // TODO version or md5 checksum - - public DefaultTopicRuntimeDataManager(NamesrvConfig config) { - namesrvConfig = config; - topicData = new TopicRuntimeData(); - changeSpread = new ChangeSpreadProcessor(namesrvConfig); - - lock = new ReentrantReadWriteLock(); - readLock = lock.readLock(); - writeLock = lock.writeLock(); - } - - - public boolean init() { - - // سʼ - if (!loadBrokerList() || !loadOrderConf()) - return false; - - changeSpread.init(); - return true; - } - - - private boolean loadBrokerList() { - try { - String content = MixAll.file2String(namesrvConfig.getBrokerAddrConfPath()); - if (null == content) - return true; - - String[] addresses = content.split(";"); - List array = new ArrayList(); - for (String addr : addresses) { - array.add(addr); - } - topicData.setBrokerList(array); - topicData.firePropertyChange("brokerList", null, array); - - if (log.isInfoEnabled()) - log.info("load broker list:" + content); - return true; - } - catch (Exception e) { - // TODO log - - } - return false; - } - - - private boolean loadOrderConf() { - try { - File file = new File(namesrvConfig.getOrderConfPath()); - if (!file.exists()) - return true; - - FileInputStream fis = new FileInputStream(file); - Properties propers = new Properties(); - propers.load(fis); - Map topicOrderConfs = new HashMap(); - for (Entry entry : propers.entrySet()) { - String key = (String) entry.getKey(); - if (!topicOrderConfs.containsKey(key)) - topicOrderConfs.put(key, (String) entry.getValue()); - } - topicData.setTopicOrderConfs(topicOrderConfs); - fis.close(); - if (log.isInfoEnabled()) - log.info("load topic order conf:\n" + propers); - return true; - } - catch (Exception e) { - // TODO log - - e.printStackTrace(); - } - return false; - } - - - public int merge(TopicRuntimeData newTopicData) { - boolean equal = false; - - readLock.lock(); - try { - equal = topicData.equals(newTopicData); - } - catch (Exception e) { - // TODO - } - finally { - readLock.unlock(); - } - - if (!equal) { - writeLock.lock(); - try { - return doMerge(newTopicData); - } - catch (Throwable e) { - // TODO log - - e.printStackTrace(); - return SYS_ERROR; - } - finally { - writeLock.unlock(); - } - } - - return NOT_MERGE; - } - - - private int doMerge(TopicRuntimeData newTopicData) { - if (log.isInfoEnabled()) - log.info("namesrv data merge start ..."); - - MergeResultHolder ret = new MergeResultHolder(); - - // if(!ObjectConverter.equals(topicData.getTopicBrokers(), - // newTopicData.getTopicBrokers())) { - // topicData.setTopicBrokers(mergeMap(topicData.getTopicBrokers(), - // newTopicData.getTopicBrokers(), ret)); - // } - - if (!ObjectConverter.equals(topicData.getTopicOrderConfs(), newTopicData.getTopicOrderConfs())) { - topicData.setTopicOrderConfs(mergeMap(topicData.getTopicOrderConfs(), - newTopicData.getTopicOrderConfs(), ret)); - storeOrderTopic(); - } - - // if(!ObjectConverter.equals(topicData.getBrokers(), - // newTopicData.getBrokers())) { - // topicData.setBrokers(mergeMap(topicData.getBrokers(), - // newTopicData.getBrokers(), ret)); - // } - - if (!ObjectConverter.equals(topicData.getBrokerList(), newTopicData.getBrokerList())) { - topicData.setBrokerList(mergeList(topicData.getBrokerList(), newTopicData.getBrokerList())); - storeBrokerList(); - } - - if (log.isInfoEnabled()) - log.info("namesrv data merge end ..."); - - return ret.getResult(); - } - - - private Map mergeMap(Map oldMap, Map newMap, MergeResultHolder holder) { - Map r = new HashMap(); - for (Entry entry : oldMap.entrySet()) { - K oldKey = entry.getKey(); - V oldV = entry.getValue(); - if (newMap.containsKey(oldKey)) { - if (null == oldV || oldV.equals(newMap.get(oldKey))) { - r.put(oldKey, null == oldV ? newMap.get(oldKey) : oldV); - } - else { - holder.setResult(MERGE_INVALID); - - // keyֵͬͬ,زһ± - log.error("fetal error merge inconsistent data, key:" + oldKey + ",local value:" + oldV - + ",remote value:" + newMap.get(oldKey)); - - } - } - else { - r.put(oldKey, oldV); - } - } - - for (Entry entry : newMap.entrySet()) { - K newKey = entry.getKey(); - if (!oldMap.containsKey(newKey)) { - r.put(newKey, entry.getValue()); - } - } - - return r; - } - - - private List mergeList(List oldList, List newList) { - List r = new ArrayList(); - r.addAll(oldList); - for (E e : newList) { - if (!r.contains(e)) - r.add(e); - } - return r; - } - - - private Result spreadSuccess(FutureGroup future) { - Result result = Result.SUCCESS; - try { - for (Entry> entry : future.getResultMap().entrySet()) { - if (!entry.getValue().get().isSuccess()) { - result = new Result(false, future.detailInfo()); - break; - } - } - } - catch (Exception e) { - // exception handle - log.error(Localhost + " spreadSuccess exception", e); - result = new Result(false, Localhost + " spreadSuccess exception" + e.getMessage()); - } - - return result; - } - - - @Override - public RemotingCommand getRouteInfoByTopic(String topic) { - RemotingCommand response = RemotingCommand.createResponseCommand(null); - TopicRouteData snapshot = doGetRouteInfoByTopic(topic); - if (null != snapshot) { - response.setBody(snapshot.encode()); - response.setCode(SUCCESS_VALUE); - } - else { - response.setCode(TOPIC_NOT_EXIST_VALUE); - response.setRemark("No topic config in this Name Server."); - } - - return response; - } - - - private TopicRouteData doGetRouteInfoByTopic(String topic) { - readLock.lock(); - try { - List queueDatas = topicData.getTopicBrokers().get(topic); - if (null != queueDatas) { - TopicRouteData topicRouteData = new TopicRouteData(); - topicRouteData.setQueueDatas(queueDatas); - List brokerDatas = new ArrayList(); - for (QueueData queueData : queueDatas) { - if (topicData.getBrokers().containsKey(queueData.getBrokerName())) { - brokerDatas.add(topicData.getBrokers().get(queueData.getBrokerName())); - } - } - topicRouteData.setBrokerDatas(brokerDatas); - topicRouteData.setOrderTopicConf(topicData.getOrderConfByTopic(topic)); - - return topicRouteData; - } - } - finally { - readLock.unlock(); - } - return null; - } - - - @Override - public RemotingCommand getTopicRuntimeData() { - RemotingCommand response = RemotingCommand.createResponseCommand(null); - byte[] data = serializeTopicRuntimeData(); - response.setBody(data); - response.setCode(SUCCESS_VALUE); - return response; - } - - - public byte[] serializeTopicRuntimeData() { - readLock.lock(); - try { - return topicData.encodeSpecific(); - } - finally { - readLock.unlock(); - } - } - - - @Override - public RemotingCommand registerBrokerSingle(String address) { - RemotingCommand response = RemotingCommand.createResponseCommand(null); - doRegisterBroker(address); - response.setCode(SUCCESS_VALUE); - - if (log.isInfoEnabled()) - log.info("register broker single, address:" + address); - - return response; - } - - - @Override - public RemotingCommand registerBroker(String address) { - RemotingCommand response = RemotingCommand.createResponseCommand(null); - if (null == address || "".equals(address)) { - response.setCode(MQResponseCode.REGISTER_BROKER_FAIL_VALUE); - response.setRemark("empty address"); - return response; - } - - // register to local - doRegisterBroker(address); - - // spread to other namesrv - FutureGroup future = changeSpread.spreadChange(REG_BROKER, new String[] { address }); - - // set return value - Result result = future.await(namesrvConfig.getGroupWaitTimeout()); - if (result.isSuccess()) { - result = spreadSuccess(future); - if (result.isSuccess()) { - response.setCode(SUCCESS_VALUE); - } - else { - response.setCode(REGISTER_BROKER_FAIL_VALUE); - response.setRemark(result.getDetail()); - } - } - else { - response.setCode(REGISTER_BROKER_TIMEOUT_VALUE); - response.setRemark(result.getDetail()); - } - - if (log.isInfoEnabled()) - log.info("register broker and spread to others, address:" + address + ",result:" + result.isSuccess() - + ",code:" + response.getCode()); - - return response; - } - - - public void doRegisterBroker(String address) { - readLock.lock(); - try { - List brokerList = topicData.getBrokerList(); - if (!brokerList.contains(address)) { - brokerList.add(address); - storeBrokerList(); - topicData.firePropertyChange("brokerList", null, null); - } - } - finally { - readLock.unlock(); - } - } - - - private void storeOrderTopic() { - String content = topicData.encodeOrderTopicAsString(); - String fileName = namesrvConfig.getOrderConfPath(); - boolean success = MixAll.string2File(content, fileName); - - log.info("store order topic in local " + success); - } - - - private void storeBrokerList() { - String content = topicData.encodeBrokerListAsString(); - String fileName = namesrvConfig.getBrokerAddrConfPath(); - boolean success = MixAll.string2File(content, fileName); - - log.info("store broker list in local " + success); - } - - - /** - * - * @param topic - * @param orderConf - */ - public boolean doRegisterOrderTopic(String topic, String orderConf) { - boolean success = true; - readLock.lock(); - try { - Map orderTopicConf = topicData.getTopicOrderConfs(); - String key = ORDER_PREFIX + topic; - if (orderTopicConf.containsKey(key)) { - String oldOrderConf = orderTopicConf.get(key); - if (oldOrderConf != null && !oldOrderConf.equals(orderConf)) { - success = false; - - // keyֵͬͬ,زһ± - log.error("fetal error register order topic, key:" + key + ",local value:" + oldOrderConf - + ",remote value:" + orderConf); - } - } - else { - orderTopicConf.put(key, orderConf); - if (log.isInfoEnabled()) - log.info("start register order topic, topic:" + key + ",order conf:" + orderConf); - // store in local - storeOrderTopic(); - } - } - finally { - readLock.unlock(); - } - - return success; - } - - - @Override - public RemotingCommand registerOrderTopic(String topic, String orderConf) { - RemotingCommand response = RemotingCommand.createResponseCommand(null); - - if (!doRegisterOrderTopic(topic, orderConf)) { - response.setCode(REGISTER_ORDER_TOPIC_FAIL_VALUE); - return response; - } - - FutureGroup future = changeSpread.spreadChange(REG_TOPIC, new String[] { topic, orderConf }); - Result result = future.await(namesrvConfig.getGroupWaitTimeout()); - if (result.isSuccess()) { - result = spreadSuccess(future); - if (result.isSuccess()) { - response.setCode(SUCCESS_VALUE); - } - else { - response.setCode(REGISTER_ORDER_TOPIC_FAIL_VALUE); - response.setRemark(result.getDetail()); - } - } - else { - response.setCode(REGISTER_ORDER_TOPIC_TIMEOUT_VALUE); - response.setRemark(result.getDetail()); - } - - return response; - } - - - @Override - public RemotingCommand registerOrderTopicSingle(String topic, String orderConf) { - RemotingCommand response = RemotingCommand.createResponseCommand(null); - response.setCode(REGISTER_ORDER_TOPIC_FAIL_VALUE); - if (doRegisterOrderTopic(topic, orderConf)) { - response.setCode(SUCCESS_VALUE); - } - - return response; - } - - - @Override - public RemotingCommand unRegisterBroker(String brokerName) { - RemotingCommand response = RemotingCommand.createResponseCommand(null); - if (null == brokerName || "".equals(brokerName)) { - response.setCode(MQResponseCode.UNREGISTER_BROKER_FAIL_VALUE); - response.setRemark("empty brokerName"); - return response; - } - - if (doUnRegisterBroker(brokerName)) { - response.setCode(MQResponseCode.UNREGISTER_BROKER_FAIL_VALUE); - // FIXME detail info - response.setRemark(""); - } - - // spread to other namesrv - FutureGroup future = changeSpread.spreadChange(UNREG_BROKER, new String[] { brokerName }); - // set return value - Result result = future.await(namesrvConfig.getGroupWaitTimeout()); - if (result.isSuccess()) { - result = spreadSuccess(future); - if (result.isSuccess()) { - response.setCode(SUCCESS_VALUE); - } - else { - response.setCode(UNREGISTER_BROKER_FAIL_VALUE); - response.setRemark(result.getDetail()); - } - } - else { - response.setCode(UNREGISTER_BROKER_TIMEOUT_VALUE); - response.setRemark(result.getDetail()); - } - - if (log.isInfoEnabled()) - log.info("register broker and spread to others, brokername:" + brokerName + ",result:" - + result.isSuccess() + ",code:" + response.getCode()); - - return response; - } - - - @Override - public RemotingCommand unRegisterBrokerSingle(String brokerName) { - RemotingCommand response = RemotingCommand.createResponseCommand(null); - response.setCode(UNREGISTER_BROKER_FAIL_VALUE); - if (doUnRegisterBroker(brokerName)) { - response.setCode(SUCCESS_VALUE); - } - - return response; - } - - - @Override - public boolean mergeQueueData(Map queueDataMap) { - writeLock.lock(); - try { - Map> queueMap = topicData.getTopicBrokers(); - for (Entry entry : queueDataMap.entrySet()) { - String newKey = entry.getKey(); - QueueData newQueueData = entry.getValue(); - if (queueMap.containsKey(newKey)) { - boolean append = true; - List oldQueues = queueMap.get(newKey); - for (QueueData old : oldQueues) { - if (old.getBrokerName().equals(newQueueData.getBrokerName())) { - oldQueues.remove(old); - oldQueues.add(newQueueData); - append = false; - break; - } - } - if (append) - oldQueues.add(newQueueData); - } - else { - List queues = new ArrayList(); - queues.add(newQueueData); - queueMap.put(newKey, queues); - } - } - } - finally { - writeLock.unlock(); - } - - return true; - } - - - @Override - public boolean mergeBrokerData(String brokerName, long brokerId, String address) { - writeLock.lock(); - try { - Map brokerMap = topicData.getBrokers(); - if (brokerMap.containsKey(brokerName)) { - BrokerData brokerData = brokerMap.get(brokerName); - brokerData.getBrokerAddrs().put(brokerId, address); - } - else { - BrokerData brokerData = new BrokerData(); - brokerData.setBrokerName(brokerName); - HashMap addrMap = new HashMap(); - addrMap.put(brokerId, address); - brokerData.setBrokerAddrs(addrMap); - brokerMap.put(brokerName, brokerData); - } - } - finally { - writeLock.unlock(); - } - - return true; - } - - - public boolean doUnRegisterBroker(String brokerName) { - writeLock.lock(); - try { - // remove broker - topicData.getBrokers().remove(brokerName); - - // remove topic info - Iterator>> iterator = topicData.getTopicBrokers().entrySet().iterator(); - while (iterator.hasNext()) { - Entry> entry = iterator.next(); - List listQueue = entry.getValue(); - Iterator iterQueueData = listQueue.iterator(); - while (iterQueueData.hasNext()) { - QueueData queueData = iterQueueData.next(); - if (queueData.getBrokerName().equals(brokerName)) { - iterQueueData.remove(); - } - } - if (listQueue.size() <= 0) - iterator.remove(); - } - - return true; - } - finally { - writeLock.unlock(); - } - } - - - @Override - public RemotingCommand unRegisterBrokerByAddr(String addr) { - if (null == addr || "".equals(addr)) - return null; - String brokerName = findBrokerNameByAddr(addr); - return this.unRegisterBroker(brokerName); - } - - - @Override - public RemotingCommand unRegisterBrokerSingleByAddr(String addr) { - if (null == addr || "".equals(addr)) - return null; - - String brokerName = findBrokerNameByAddr(addr); - return this.unRegisterBrokerSingle(brokerName); - } - - - private String findBrokerNameByAddr(String addr) { - readLock.lock(); - try { - for (Entry entry : topicData.getBrokers().entrySet()) { - BrokerData brokerData = entry.getValue(); - for (Entry brokerEntry : brokerData.getBrokerAddrs().entrySet()) { - if (brokerEntry.getValue().equals(addr)) - return brokerData.getBrokerName(); - } - } - return null; - } - finally { - readLock.unlock(); - } - } - - - @Override - public ArrayList getBrokerList() { - return (ArrayList) ((ArrayList) topicData.getBrokerList()).clone(); - } - - - @Override - public void shutdown() { - changeSpread.shutdown(); - } - - - public void addPropertyChangeListener(final String propertyName, final PropertyChangeListener listener) { - topicData.addPropertyChangeListener(propertyName, listener); - } - - - public void removePropertyChangeListener(final PropertyChangeListener listener) { - topicData.removePropertyChangeListener(listener); - } - - - public void firePropertyChange(String propertyName, Object oldValue, Object newValue) { - topicData.firePropertyChange(propertyName, oldValue, newValue); - } - -} diff --git a/rocketmq-namesrv/src/main/java/com/alibaba/rocketmq/namesrv/topic/NamesrvConfigManager.java b/rocketmq-namesrv/src/main/java/com/alibaba/rocketmq/namesrv/topic/NamesrvConfigManager.java deleted file mode 100644 index f4008bc8..00000000 --- a/rocketmq-namesrv/src/main/java/com/alibaba/rocketmq/namesrv/topic/NamesrvConfigManager.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.alibaba.rocketmq.namesrv.topic; - -/** - * ṩnamesrvconfigö̬޸Ĺ - * - * @auther lansheng.zj@taobao.com - */ -public interface NamesrvConfigManager { - // FIXME - -} diff --git a/rocketmq-namesrv/src/main/java/com/alibaba/rocketmq/namesrv/topic/TopicRuntimeDataManager.java b/rocketmq-namesrv/src/main/java/com/alibaba/rocketmq/namesrv/topic/TopicRuntimeDataManager.java deleted file mode 100644 index 670e7b4f..00000000 --- a/rocketmq-namesrv/src/main/java/com/alibaba/rocketmq/namesrv/topic/TopicRuntimeDataManager.java +++ /dev/null @@ -1,193 +0,0 @@ -package com.alibaba.rocketmq.namesrv.topic; - -import java.beans.PropertyChangeListener; -import java.util.ArrayList; -import java.util.Map; - -import com.alibaba.rocketmq.common.namesrv.TopicRuntimeData; -import com.alibaba.rocketmq.common.protocol.route.QueueData; -import com.alibaba.rocketmq.namesrv.common.MergeResult; -import com.alibaba.rocketmq.remoting.protocol.RemotingCommand; - - -/** - * @author lansheng.zj@taobao.com - */ -public interface TopicRuntimeDataManager { - - // - // public void getBrokerList(); - // public void registerOrderTopic(); - // public void unRegisterOrderTopic(); - // public void getOrderTopicList(); - - /** - * ȡtopic·Ϣ - * - * @param topic - */ - public RemotingCommand getRouteInfoByTopic(String topic); - - - /** - * ȡTopicRuntimeDataһsnapshot - * - * @return - */ - public RemotingCommand getTopicRuntimeData(); - - - /** - * ϲTopicRuntimeData - * - * @param newTopicData - * @return ϲĽ {@link MergeResult} - */ - public int merge(TopicRuntimeData newTopicData); - - - /** - * עbrokerַأɢnamesrv - * - * @param address - * brokerַ - * @return - */ - public RemotingCommand registerBroker(String address); - - - /** - * עbrokerַ - * - * @param address - * @return - */ - public RemotingCommand registerBrokerSingle(String address); - - - /** - * עעbrokerɢnamesrv - * - * @param brokerName - * עbrokername - * @return - */ - public RemotingCommand unRegisterBroker(String brokerName); - - - /** - * עעbroker - * - * @param brokerName - * עbrokername - * @return - */ - public RemotingCommand unRegisterBrokerSingle(String brokerName); - - - /** - * ע˳Ϣõأɢnamesrv - * - * @param topic - * @param orderConf - * @return - */ - public RemotingCommand registerOrderTopic(String topic, String orderConf); - - - /** - * ע˳Ϣõ - * - * @param topic - * @param orderConf - * @return - */ - public RemotingCommand registerOrderTopicSingle(String topic, String orderConf); - - - /** - * ϲQueueData - * - * @param queueDataMap - * @return - */ - public boolean mergeQueueData(Map queueDataMap); - - - /** - * ϲBrokerData - * - * @param brokerName - * @param brokerId - * @param address - * @return - */ - public boolean mergeBrokerData(String brokerName, long brokerId, String address); - - - /** - * עַΪaddrbroker - * - * @param addr - * @return - */ - public RemotingCommand unRegisterBrokerSingleByAddr(String addr); - - - /** - * עַΪaddrbroker - * @param addr - * @return - */ - public RemotingCommand unRegisterBrokerByAddr(String addr); - - - /** - * رգԴ - */ - public void shutdown(); - - - /** - * ȡbrokerַб - * - * @return - */ - public ArrayList getBrokerList(); - - - /** - * ʼ - * - * @return - */ - public boolean init(); - - - /** - * add property change listener - * - * @param propertyName - * @param listener - */ - public void addPropertyChangeListener(final String propertyName, final PropertyChangeListener listener); - - - /** - * remove property change listener - * - * @param listener - */ - public void removePropertyChangeListener(final PropertyChangeListener listener); - - - /** - * fire property change - * - * @param propertyName - * @param oldValue - * @param newValue - */ - public void firePropertyChange(String propertyName, Object oldValue, Object newValue); - -} diff --git a/rocketmq-namesrv/src/test/java/com/alibaba/rocketmq/namesrv/DataUtils.java b/rocketmq-namesrv/src/test/java/com/alibaba/rocketmq/namesrv/DataUtils.java deleted file mode 100644 index 876c38e8..00000000 --- a/rocketmq-namesrv/src/test/java/com/alibaba/rocketmq/namesrv/DataUtils.java +++ /dev/null @@ -1,229 +0,0 @@ -package com.alibaba.rocketmq.namesrv; - -import java.lang.reflect.Field; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Random; - -import com.alibaba.rocketmq.common.namesrv.TopicRuntimeData; -import com.alibaba.rocketmq.common.protocol.route.BrokerData; -import com.alibaba.rocketmq.common.protocol.route.QueueData; - - -/** - * @auther lansheng.zj@taobao.com - */ -public class DataUtils { - - public static TopicRuntimeData createSpecific1() { - TopicRuntimeData data = new TopicRuntimeData(); - - data.getTopicOrderConfs().put("topic.num.topic-1", "105:4;106:4"); - data.getTopicOrderConfs().put("topic.num.andor-applye-test", "105:4;106:4"); - - data.getBrokerList().add("10.23.12.12:8123"); - data.getBrokerList().add("10.23.12.13:8123"); - data.getBrokerList().add("10.23.12.14:8123"); - data.getBrokerList().add("10.23.12.15:8123"); - - return data; - } - - - public static TopicRuntimeData createSpecific2() { - TopicRuntimeData data = new TopicRuntimeData(); - - data.getTopicOrderConfs().put("topic.num.topic-1", "105:4;106:4"); - data.getTopicOrderConfs().put("topic.num.andor-applye-test", "105:4;106:4"); - - data.getBrokerList().add("10.23.12.12:8123"); - data.getBrokerList().add("10.23.12.13:8123"); - data.getBrokerList().add("10.23.12.100:8123"); - data.getBrokerList().add("10.23.12.101:8123"); - - return data; - } - - - public static TopicRuntimeData createExpect() { - TopicRuntimeData data = new TopicRuntimeData(); - - data.getTopicOrderConfs().put("topic.num.topic-1", "105:4;106:4"); - data.getTopicOrderConfs().put("topic.num.andor-applye-test", "105:4;106:4"); - - data.getBrokerList().add("10.23.12.12:8123"); - data.getBrokerList().add("10.23.12.13:8123"); - data.getBrokerList().add("10.23.12.14:8123"); - data.getBrokerList().add("10.23.12.15:8123"); - data.getBrokerList().add("10.23.12.100:8123"); - data.getBrokerList().add("10.23.12.101:8123"); - - return data; - } - - - public static TopicRuntimeData createOne() { - TopicRuntimeData data = new TopicRuntimeData(); - QueueData queueData1 = new QueueData(); - queueData1.setBrokerName("broker-1"); - queueData1.setPerm(4); - queueData1.setReadQueueNums(4); - queueData1.setWriteQueueNums(4); - - List queueDatas1 = new ArrayList(); - queueDatas1.add(queueData1); - - List queueDatas2 = new ArrayList(); - queueDatas2.add(queueData1); - - data.getTopicBrokers().put("topic-1", queueDatas1); - data.getTopicBrokers().put("topic-2", queueDatas2); - - data.getTopicOrderConfs().put("topic.num.topic-1", "105:4;106:4"); - data.getTopicOrderConfs().put("topic.num.andor-applye-test", "105:4;106:4"); - - BrokerData broker1 = new BrokerData(); - broker1.setBrokerName("broker-1"); - HashMap brokerAddrs1 = new HashMap(); - brokerAddrs1.put(0L, "10.23.12.12:8123"); - broker1.setBrokerAddrs(brokerAddrs1); - - data.getBrokers().put("broker-1", broker1); - - data.getBrokerList().add("10.23.12.12:8123"); - data.getBrokerList().add("10.23.12.13:8123"); - data.getBrokerList().add("10.23.12.14:8123"); - data.getBrokerList().add("10.23.12.15:8123"); - - return data; - } - - - public static TopicRuntimeData create() { - TopicRuntimeData data = new TopicRuntimeData(); - QueueData queueData1 = new QueueData(); - queueData1.setBrokerName("broker-1"); - queueData1.setPerm(4); - queueData1.setReadQueueNums(4); - queueData1.setWriteQueueNums(4); - - QueueData queueData2 = new QueueData(); - queueData2.setBrokerName("broker-2"); - queueData2.setPerm(4); - queueData2.setReadQueueNums(4); - queueData2.setWriteQueueNums(4); - - QueueData queueData3 = new QueueData(); - queueData3.setBrokerName("broker-3"); - queueData3.setPerm(4); - queueData3.setReadQueueNums(4); - queueData3.setWriteQueueNums(4); - - QueueData queueData4 = new QueueData(); - queueData4.setBrokerName("broker-4"); - queueData4.setPerm(4); - queueData4.setReadQueueNums(4); - queueData4.setWriteQueueNums(4); - - List queueDatas1 = new ArrayList(); - queueDatas1.add(queueData1); - queueDatas1.add(queueData2); - - List queueDatas2 = new ArrayList(); - queueDatas2.add(queueData1); - queueDatas2.add(queueData3); - queueDatas2.add(queueData4); - - data.getTopicBrokers().put("topic-1", queueDatas1); - data.getTopicBrokers().put("topic-2", queueDatas2); - - data.getTopicOrderConfs().put("topic.num.topic-1", "105:4;106:4"); - data.getTopicOrderConfs().put("topic.num.andor-applye-test", "105:4;106:4"); - - BrokerData broker1 = new BrokerData(); - broker1.setBrokerName("broker-1"); - HashMap brokerAddrs1 = new HashMap(); - brokerAddrs1.put(0L, "10.23.12.12:8123"); - broker1.setBrokerAddrs(brokerAddrs1); - - BrokerData broker2 = new BrokerData(); - broker2.setBrokerName("broker-2"); - HashMap brokerAddrs2 = new HashMap(); - brokerAddrs2.put(0L, "10.23.12.13:8123"); - broker2.setBrokerAddrs(brokerAddrs2); - - BrokerData broker3 = new BrokerData(); - broker3.setBrokerName("broker-3"); - HashMap brokerAddrs3 = new HashMap(); - brokerAddrs3.put(0L, "10.23.12.14:8123"); - broker3.setBrokerAddrs(brokerAddrs3); - - BrokerData broker4 = new BrokerData(); - broker4.setBrokerName("broker-4"); - HashMap brokerAddrs4 = new HashMap(); - // brokerAddrs4.put(0L, "10.23.12.15:8123"); - broker4.setBrokerAddrs(brokerAddrs4); - - data.getBrokers().put("broker-1", broker1); - data.getBrokers().put("broker-2", broker2); - data.getBrokers().put("broker-3", broker3); - data.getBrokers().put("broker-4", broker4); - - data.getBrokerList().add("10.23.12.12:8123"); - data.getBrokerList().add("10.23.12.13:8123"); - data.getBrokerList().add("10.23.12.14:8123"); - data.getBrokerList().add("10.23.12.15:8123"); - - return data; - } - - - public static QueueData createQueueData() { - QueueData queueData1 = new QueueData(); - queueData1.setBrokerName(createBrokerName()); - queueData1.setPerm(4); - queueData1.setReadQueueNums(4); - queueData1.setWriteQueueNums(4); - - return queueData1; - } - - - public static String createBrokerName() { - return "broker-" + randomInt(1000); - } - - - public static String createAddr() { - return "" + randomInt(256) + "." + randomInt(256) + "." + randomInt(256) + "." + randomInt(256) - + ":8123"; - } - - - public static String createTopic() { - return "topic-" + randomInt(1000); - } - - - public static int randomInt(int ratio) { - Random random = new Random(System.currentTimeMillis()); - return Math.abs(random.nextInt()) % ratio; - } - - - public static void hackField(T target, V value, String fieldName) throws Exception { - Field field = target.getClass().getDeclaredField(fieldName); - field.setAccessible(true); - field.set(target, value); - } - - - public static F getField(T target, Class fieldClazz, String fieldName) - throws Exception { - Field field = target.getClass().getDeclaredField(fieldName); - field.setAccessible(true); - F fieldObj = (F)field.get(target); - return fieldObj; - } -} diff --git a/rocketmq-namesrv/src/test/java/com/alibaba/rocketmq/namesrv/daemon/NamesrvClientTest.java b/rocketmq-namesrv/src/test/java/com/alibaba/rocketmq/namesrv/daemon/NamesrvClientTest.java deleted file mode 100644 index 999c6f71..00000000 --- a/rocketmq-namesrv/src/test/java/com/alibaba/rocketmq/namesrv/daemon/NamesrvClientTest.java +++ /dev/null @@ -1,128 +0,0 @@ -package com.alibaba.rocketmq.namesrv.daemon; - -import static org.easymock.EasyMock.anyLong; -import static org.easymock.EasyMock.anyObject; -import static org.easymock.EasyMock.eq; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import junit.framework.Assert; - -import org.apache.commons.io.IOUtils; -import org.easymock.EasyMock; -import org.junit.Before; -import org.junit.Test; - -import com.alibaba.rocketmq.common.MixAll; -import com.alibaba.rocketmq.common.TopicConfig; -import com.alibaba.rocketmq.common.namesrv.NamesrvConfig; -import com.alibaba.rocketmq.common.namesrv.TopicRuntimeData; -import com.alibaba.rocketmq.common.protocol.header.namesrv.GetTopicResponseHeader; -import com.alibaba.rocketmq.namesrv.DataUtils; -import com.alibaba.rocketmq.namesrv.common.Result; -import com.alibaba.rocketmq.namesrv.sync.FutureGroup; -import com.alibaba.rocketmq.namesrv.topic.DefaultTopicRuntimeDataManager; -import com.alibaba.rocketmq.remoting.RemotingClient; -import com.alibaba.rocketmq.remoting.netty.NettyClientConfig; -import com.alibaba.rocketmq.remoting.protocol.RemotingCommand; -import com.alibaba.rocketmq.remoting.protocol.RemotingProtos.ResponseCode; - - -/** - * @auther lansheng.zj@taobao.com - */ -public class NamesrvClientTest { - - private RemotingClient remotingClient; - - - @Before - public void init() { - remotingClient = EasyMock.createMock(RemotingClient.class); - } - - - @Test - public void testGroupCommit() throws Exception { - Map topicConfigTable = create(); - String content = encode(topicConfigTable); - RemotingCommand response1 = RemotingCommand.createResponseCommand(GetTopicResponseHeader.class); - response1.setBody(content.getBytes(MixAll.DEFAULT_CHARSET)); - - GetTopicResponseHeader getTopicResponseHeader=(GetTopicResponseHeader)response1.getCustomHeader(); - getTopicResponseHeader.setVersion("version"); - getTopicResponseHeader.setBrokerName("broker-019"); - getTopicResponseHeader.setBrokerId(0); - getTopicResponseHeader.setCluster("cluster"); - response1.setCode(ResponseCode.SUCCESS_VALUE); - response1.setRemark(null); - - RemotingCommand response2 = RemotingCommand.createResponseCommand(GetTopicResponseHeader.class); - response2.setBody(content.getBytes(MixAll.DEFAULT_CHARSET)); - - GetTopicResponseHeader getTopicResponseHeader2=(GetTopicResponseHeader)response2.getCustomHeader(); - getTopicResponseHeader2.setVersion("version"); - getTopicResponseHeader2.setBrokerName("broker-019"); - getTopicResponseHeader2.setBrokerId(0); - getTopicResponseHeader2.setCluster("cluster"); - response2.setCode(ResponseCode.SUCCESS_VALUE); - response2.setRemark(null); - - EasyMock - .expect( - remotingClient.invokeSync(eq("12.12.13.4:8123"), anyObject(RemotingCommand.class), - anyLong())).andReturn(response1).anyTimes(); - EasyMock - .expect( - remotingClient.invokeSync(eq("12.12.13.89:8123"), anyObject(RemotingCommand.class), - anyLong())).andReturn(response2).anyTimes(); - EasyMock.replay(remotingClient); - - NamesrvConfig namesrvConfig = new NamesrvConfig(); - namesrvConfig.setNamesrvAddr("120.21.21.12:9876;120.21.21.11:9876;"); - List brokerList = new ArrayList(); - brokerList.add("12.12.13.4:8123"); - brokerList.add("12.12.13.89:8123"); - DefaultTopicRuntimeDataManager dataManager = new DefaultTopicRuntimeDataManager(namesrvConfig); - TopicRuntimeData topicRuntimeData = DataUtils.getField(dataManager, TopicRuntimeData.class, "topicData"); - - topicRuntimeData.setBrokerList(brokerList); - - NettyClientConfig nettyClientConfig = new NettyClientConfig(); - - NamesrvClient namesrvClient = new NamesrvClient(namesrvConfig, nettyClientConfig, dataManager); - DataUtils.hackField(namesrvClient, remotingClient, "remotingClient"); - - FutureGroup futureGroup = namesrvClient.groupCommit(); - Result result = namesrvClient.pullSuccess(futureGroup); - - Assert.assertTrue(result.isSuccess()); - Assert.assertTrue("12.12.13.4:8123".equals(topicRuntimeData.getBrokers().get("broker-019") - .getBrokerAddrs().get(0L))); - } - - - private Map create() { - Map topicConfigTable = new HashMap(1024); - topicConfigTable.put("topic-909", new TopicConfig("topic-909", 4, 4, 4)); - topicConfigTable.put("topic-910", new TopicConfig("topic-910", 4, 4, 4)); - return topicConfigTable; - } - - - private String encode(Map topicConfigTable) { - if (!topicConfigTable.isEmpty()) { - StringBuilder sb = new StringBuilder(); - for (TopicConfig config : topicConfigTable.values()) { - sb.append(config.getTopicName() + "=" + config.encode() + IOUtils.LINE_SEPARATOR); - } - - return sb.toString(); - } - - return null; - } -} diff --git a/rocketmq-namesrv/src/test/java/com/alibaba/rocketmq/namesrv/daemon/NamesrvSyncTest.java b/rocketmq-namesrv/src/test/java/com/alibaba/rocketmq/namesrv/daemon/NamesrvSyncTest.java deleted file mode 100644 index 58f06792..00000000 --- a/rocketmq-namesrv/src/test/java/com/alibaba/rocketmq/namesrv/daemon/NamesrvSyncTest.java +++ /dev/null @@ -1,105 +0,0 @@ -package com.alibaba.rocketmq.namesrv.daemon; - -import static com.alibaba.rocketmq.namesrv.DataUtils.createExpect; -import static com.alibaba.rocketmq.namesrv.DataUtils.createSpecific1; -import static com.alibaba.rocketmq.namesrv.DataUtils.createSpecific2; -import static com.alibaba.rocketmq.remoting.protocol.RemotingProtos.ResponseCode.SUCCESS_VALUE; -import static org.easymock.EasyMock.anyLong; -import static org.easymock.EasyMock.anyObject; -import static org.easymock.EasyMock.eq; -import static org.easymock.EasyMock.expect; - -import junit.framework.Assert; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.powermock.api.easymock.PowerMock; -import org.powermock.core.classloader.annotations.PowerMockIgnore; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.PowerMockRunner; - -import com.alibaba.rocketmq.common.namesrv.NamesrvConfig; -import com.alibaba.rocketmq.common.namesrv.TopicRuntimeData; -import com.alibaba.rocketmq.namesrv.DataUtils; -import com.alibaba.rocketmq.namesrv.common.Result; -import com.alibaba.rocketmq.namesrv.sync.FutureGroup; -import com.alibaba.rocketmq.namesrv.topic.DefaultTopicRuntimeDataManager; -import com.alibaba.rocketmq.remoting.common.RemotingHelper; -import com.alibaba.rocketmq.remoting.protocol.RemotingCommand; - - -/** - * @auther lansheng.zj@taobao.com - */ -@RunWith(PowerMockRunner.class) -@PowerMockIgnore("com.taobao.rocketmq.common.MixAll") -@PrepareForTest({ RemotingHelper.class }) -public class NamesrvSyncTest { - - @Test - public void testGroupCommit() throws Exception { - TopicRuntimeData expected = createSpecific1(); - RemotingCommand response = RemotingCommand.createResponseCommand(null); - response.setCode(SUCCESS_VALUE); - response.setBody(expected.encode()); - - NamesrvConfig namesrvConf = new NamesrvConfig(); - namesrvConf.setNamesrvAddr("10.12.12.11:9876;10.12.12.16:9876;"); - DefaultTopicRuntimeDataManager topicRuntimeDataManager = new DefaultTopicRuntimeDataManager(namesrvConf); - NamesrvSync namesrvSync = new NamesrvSync(namesrvConf, topicRuntimeDataManager); - - PowerMock.mockStatic(RemotingHelper.class); - expect(RemotingHelper.invokeSync((String) anyObject(), (RemotingCommand) anyObject(), anyLong())) - .andReturn(response); - PowerMock.replay(RemotingHelper.class); - - FutureGroup futureGroup = namesrvSync.groupCommit(); - Result result = futureGroup.await(namesrvConf.getGroupWaitTimeout()); - - TopicRuntimeData topicRuntimeData = - DataUtils.getField(topicRuntimeDataManager, TopicRuntimeData.class, "topicData"); - - Assert.assertTrue(result.isSuccess()); - Assert.assertTrue(expected.equals(topicRuntimeData)); - } - - - @Test - public void testGroupCommitMerge() throws Exception { - TopicRuntimeData expected = createExpect(); - TopicRuntimeData specific1 = createSpecific1(); - TopicRuntimeData specific2 = createSpecific2(); - - RemotingCommand response1 = RemotingCommand.createResponseCommand(null); - response1.setCode(SUCCESS_VALUE); - response1.setBody(specific1.encode()); - RemotingCommand response2 = RemotingCommand.createResponseCommand(null); - response2.setCode(SUCCESS_VALUE); - response2.setBody(specific2.encode()); - - NamesrvConfig namesrvConf = new NamesrvConfig(); - namesrvConf.setNamesrvAddr("addr1;addr2"); - namesrvConf.setSyncTimeout(100L); - DefaultTopicRuntimeDataManager topicRuntimeDataManager = new DefaultTopicRuntimeDataManager(namesrvConf); - NamesrvSync namesrvSync = new NamesrvSync(namesrvConf, topicRuntimeDataManager); - - PowerMock.mockStatic(RemotingHelper.class); - expect( - RemotingHelper.invokeSync(eq("addr1"), anyObject(RemotingCommand.class), - eq(namesrvConf.getSyncTimeout()))).andReturn(response1).anyTimes(); - expect( - RemotingHelper.invokeSync(eq("addr2"), anyObject(RemotingCommand.class), - eq(namesrvConf.getSyncTimeout()))).andReturn(response2).anyTimes(); - PowerMock.replay(RemotingHelper.class); - - FutureGroup futureGroup = namesrvSync.groupCommit(); - Result result = futureGroup.await(namesrvConf.getGroupWaitTimeout()); - - TopicRuntimeData topicRuntimeData = - DataUtils.getField(topicRuntimeDataManager, TopicRuntimeData.class, "topicData"); - - Assert.assertTrue(result.isSuccess()); - Assert.assertTrue(expected.equals(topicRuntimeData)); - } - -} diff --git a/rocketmq-namesrv/src/test/java/com/alibaba/rocketmq/namesrv/daemon/PollingAddressTest.java b/rocketmq-namesrv/src/test/java/com/alibaba/rocketmq/namesrv/daemon/PollingAddressTest.java deleted file mode 100644 index 3e1129ec..00000000 --- a/rocketmq-namesrv/src/test/java/com/alibaba/rocketmq/namesrv/daemon/PollingAddressTest.java +++ /dev/null @@ -1,45 +0,0 @@ -package com.alibaba.rocketmq.namesrv.daemon; - -import java.util.Map; - -import org.junit.Test; - -import junit.framework.Assert; - -import com.alibaba.rocketmq.common.namesrv.NamesrvConfig; -import com.alibaba.rocketmq.namesrv.DataUtils; -import com.alibaba.rocketmq.namesrv.processor.ChangeSpreadProcessor; -import com.alibaba.rocketmq.namesrv.sync.Task; -import com.alibaba.rocketmq.namesrv.sync.TaskGroup; -import com.alibaba.rocketmq.namesrv.sync.TaskType; -import com.alibaba.rocketmq.namesrv.topic.DefaultTopicRuntimeDataManager; - - -/** - * @auther lansheng.zj@taobao.com - */ -public class PollingAddressTest { - - @Test - public void testSetAddrAndFireChange() throws Exception { - NamesrvConfig namesrvConfig = new NamesrvConfig(); - DefaultTopicRuntimeDataManager dataManager = new DefaultTopicRuntimeDataManager(namesrvConfig); - NamesrvSync namesrvSync = new NamesrvSync(namesrvConfig, dataManager); - namesrvSync.init(); - - ChangeSpreadProcessor changeSpread = new ChangeSpreadProcessor(namesrvConfig); - changeSpread.init(); - - PollingAddress pollingAddress = new PollingAddress(namesrvConfig); - pollingAddress.setAddrAndFireChange("12.123.12.31:9876;12.123.12.98:9876;"); - - TaskGroup taskGroup = DataUtils.getField(namesrvSync, TaskGroup.class, "syncTaskGroup"); - Task task = taskGroup.getTask("12.123.12.31:9876"); - Assert.assertTrue(null != task); - - Map map = DataUtils.getField(changeSpread, Map.class, "taskGroupMap"); - taskGroup = (TaskGroup) map.get(TaskType.REG_BROKER); - task = taskGroup.getTask("12.123.12.98:9876"); - Assert.assertTrue(null != task); - } -} diff --git a/rocketmq-namesrv/src/test/java/com/alibaba/rocketmq/namesrv/topic/DefaultTopicRuntimeDataManagerTest.java b/rocketmq-namesrv/src/test/java/com/alibaba/rocketmq/namesrv/topic/DefaultTopicRuntimeDataManagerTest.java deleted file mode 100644 index a7c66f78..00000000 --- a/rocketmq-namesrv/src/test/java/com/alibaba/rocketmq/namesrv/topic/DefaultTopicRuntimeDataManagerTest.java +++ /dev/null @@ -1,197 +0,0 @@ -package com.alibaba.rocketmq.namesrv.topic; - -import static com.alibaba.rocketmq.namesrv.DataUtils.create; -import static com.alibaba.rocketmq.namesrv.DataUtils.createAddr; -import static com.alibaba.rocketmq.namesrv.DataUtils.createExpect; -import static com.alibaba.rocketmq.namesrv.DataUtils.createQueueData; -import static com.alibaba.rocketmq.namesrv.DataUtils.createTopic; -import static com.alibaba.rocketmq.namesrv.common.MergeResult.MERGE_INVALID; -import static com.alibaba.rocketmq.namesrv.common.MergeResult.SYS_ERROR; -import static com.alibaba.rocketmq.remoting.protocol.RemotingProtos.ResponseCode.SUCCESS_VALUE; -import static org.easymock.EasyMock.anyLong; -import static org.easymock.EasyMock.anyObject; - -import java.util.HashMap; -import java.util.Map; - -import junit.framework.Assert; - -import org.easymock.EasyMock; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.powermock.api.easymock.PowerMock; -import org.powermock.core.classloader.annotations.PowerMockIgnore; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.PowerMockRunner; - -import com.alibaba.rocketmq.common.namesrv.NamesrvConfig; -import com.alibaba.rocketmq.common.namesrv.TopicRuntimeData; -import com.alibaba.rocketmq.common.protocol.route.QueueData; -import com.alibaba.rocketmq.common.protocol.route.TopicRouteData; -import com.alibaba.rocketmq.namesrv.DataUtils; -import com.alibaba.rocketmq.remoting.common.RemotingHelper; -import com.alibaba.rocketmq.remoting.protocol.RemotingCommand; -import com.alibaba.rocketmq.remoting.protocol.RemotingProtos.ResponseCode; - - -/** - * @auther lansheng.zj@taobao.com - */ -@RunWith(PowerMockRunner.class) -@PowerMockIgnore("com.alibaba.rocketmq.common.MixAll") -@PrepareForTest({ RemotingHelper.class }) -public class DefaultTopicRuntimeDataManagerTest { - - private DefaultTopicRuntimeDataManager dataManager; - - - @Before - public void init() { - NamesrvConfig namesrvConfig = new NamesrvConfig(); - namesrvConfig.setNamesrvAddr("10.232.133.1:9876;10.232.133.2:9876;"); - dataManager = new DefaultTopicRuntimeDataManager(namesrvConfig); - dataManager.init(); - } - - - @Test - public void testMerge() throws Exception { - TopicRuntimeData expected = createExpect(); - int code = dataManager.merge(expected); - TopicRuntimeData topicRuntimeData = DataUtils.getField(dataManager, TopicRuntimeData.class, "topicData"); - - Assert.assertTrue(MERGE_INVALID != code); - Assert.assertTrue(SYS_ERROR != code); - Assert.assertTrue(topicRuntimeData.equals(expected)); - } - - - @Test - public void testInit() throws Exception { - TopicRuntimeData expected = createExpect(); - - NamesrvConfig namesrvConfig = new NamesrvConfig(); - namesrvConfig.setNamesrvAddr("10.232.133.1:9876;10.232.133.2:9876;"); - DefaultTopicRuntimeDataManager dataManager = new DefaultTopicRuntimeDataManager(namesrvConfig); - boolean success = dataManager.init(); - - TopicRuntimeData topicRuntimeData = DataUtils.getField(dataManager, TopicRuntimeData.class, "topicData"); - - Assert.assertTrue(success); - Assert.assertTrue(topicRuntimeData.equals(expected)); - } - - - @Test - public void testGetRouteInfoByTopic() throws Exception { - String topic = "topic-1"; - DataUtils.hackField(dataManager, create(), "topicData"); - RemotingCommand response = dataManager.getRouteInfoByTopic(topic); - Assert.assertTrue(response.getCode() == ResponseCode.SUCCESS_VALUE); - - TopicRouteData topicRouteData = TopicRouteData.decode(response.getBody()); - Assert.assertTrue("topic.num.topic-1=105:4;106:4".equals(topicRouteData.getOrderTopicConf())); - } - - - @Test - public void testGetTopicRuntimeData() throws Exception { - DataUtils.hackField(dataManager, DataUtils.createExpect(), "topicData"); - RemotingCommand response = dataManager.getTopicRuntimeData(); - Assert.assertTrue(response.getCode() == SUCCESS_VALUE); - - TopicRuntimeData data = TopicRuntimeData.decode(response.getBody()); - TopicRuntimeData topicRuntimeData = DataUtils.getField(dataManager, TopicRuntimeData.class, "topicData"); - - Assert.assertTrue(topicRuntimeData.equals(data)); - } - - - @Test - public void testRegisterBroker() throws Exception { - RemotingCommand mockResponse = RemotingCommand.createResponseCommand(null); - mockResponse.setCode(SUCCESS_VALUE); - PowerMock.mockStatic(RemotingHelper.class); - EasyMock - .expect( - RemotingHelper.invokeSync(anyObject(String.class), anyObject(RemotingCommand.class), anyLong())) - .andReturn(mockResponse).anyTimes(); - PowerMock.replay(RemotingHelper.class); - - String addr = createAddr(); - RemotingCommand response = dataManager.registerBroker(addr); - - TopicRuntimeData topicRuntimeData = DataUtils.getField(dataManager, TopicRuntimeData.class, "topicData"); - - Assert.assertTrue(response.getCode() == SUCCESS_VALUE); - Assert.assertTrue(topicRuntimeData.getBrokerList().contains(addr)); - } - - - @Test - public void testRegisterOrderTopic() throws Exception { - RemotingCommand mockResponse = RemotingCommand.createResponseCommand(null); - mockResponse.setCode(SUCCESS_VALUE); - PowerMock.mockStatic(RemotingHelper.class); - EasyMock - .expect( - RemotingHelper.invokeSync(anyObject(String.class), anyObject(RemotingCommand.class), anyLong())) - .andReturn(mockResponse).anyTimes(); - PowerMock.replay(RemotingHelper.class); - RemotingCommand response = dataManager.registerOrderTopic("topic-100", "105:4;106:4"); - - TopicRuntimeData topicRuntimeData = DataUtils.getField(dataManager, TopicRuntimeData.class, "topicData"); - - Assert.assertTrue(response.getCode() == SUCCESS_VALUE); - Assert.assertTrue("topic.num.topic-100=105:4;106:4".equals(topicRuntimeData - .getOrderConfByTopic("topic-100"))); - } - - - @Test - public void testMergeQueueData() { - boolean success = dataManager.mergeBrokerData("broker-100", 0L, createAddr()); - Assert.assertTrue(success); - } - - - @Test - public void testMergeBrokerData() throws Exception { - String topic = createTopic(); - QueueData queueData = createQueueData(); - Map map = new HashMap(); - map.put(topic, queueData); - boolean success = dataManager.mergeQueueData(map); - - TopicRuntimeData topicRuntimeData = DataUtils.getField(dataManager, TopicRuntimeData.class, "topicData"); - - Assert.assertTrue(topicRuntimeData.getTopicBrokers().get(topic).contains(queueData)); - Assert.assertTrue(success); - - success = dataManager.mergeQueueData(map); - Assert.assertTrue(topicRuntimeData.getTopicBrokers().get(topic).contains(queueData)); - Assert.assertTrue(success); - } - - - @Test - public void testDoUnRegisterBroker() throws Exception { - String brokerName = "broker-1"; - TopicRuntimeData data = DataUtils.create(); - DataUtils.hackField(dataManager, data, "topicData"); - boolean ret = dataManager.doUnRegisterBroker(brokerName); - Assert.assertTrue(ret); - } - - - @Test - public void testDoUnRegisterBrokerOne() throws Exception { - String brokerName = "broker-1"; - TopicRuntimeData data = DataUtils.createOne(); - DataUtils.hackField(dataManager, data, "topicData"); - boolean ret = dataManager.doUnRegisterBroker(brokerName); - Assert.assertTrue(ret); - } - -} diff --git a/rocketmq-qatest/pom.xml b/rocketmq-qatest/pom.xml new file mode 100644 index 00000000..e927d5b4 --- /dev/null +++ b/rocketmq-qatest/pom.xml @@ -0,0 +1,43 @@ + + + + com.alibaba.rocketmq + rocketmq-all + 3.0.8-SNAPSHOT + + 4.0.0 + rocketmq-qatest + jar + rocketmq-qatest ${project.version} + + + + junit + junit + 4.11 + test + + + ${project.groupId} + rocketmq-common + + + ${project.groupId} + rocketmq-store + + + ${project.groupId} + rocketmq-broker + + + ${project.groupId} + rocketmq-client + + + commons-lang + commons-lang + 2.6 + + + + diff --git a/rocketmq-qatest/src/test/java/com/alibaba/rocketmq/test/integration/BaseTest.java b/rocketmq-qatest/src/test/java/com/alibaba/rocketmq/test/integration/BaseTest.java new file mode 100644 index 00000000..54860df2 --- /dev/null +++ b/rocketmq-qatest/src/test/java/com/alibaba/rocketmq/test/integration/BaseTest.java @@ -0,0 +1,189 @@ +package com.alibaba.rocketmq.test.integration; + +import java.io.File; +import java.util.Random; +import java.util.concurrent.atomic.AtomicInteger; + +import org.apache.commons.lang.StringUtils; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.classic.joran.JoranConfigurator; + +import com.alibaba.rocketmq.broker.BrokerController; +import com.alibaba.rocketmq.common.BrokerConfig; +import com.alibaba.rocketmq.common.MQVersion; +import com.alibaba.rocketmq.common.MixAll; +import com.alibaba.rocketmq.common.constant.LoggerName; +import com.alibaba.rocketmq.remoting.netty.NettyClientConfig; +import com.alibaba.rocketmq.remoting.netty.NettyServerConfig; +import com.alibaba.rocketmq.remoting.protocol.RemotingCommand; +import com.alibaba.rocketmq.store.config.MessageStoreConfig; + + +/** + * @author manhong.yqd + * @since 2013-8-26 + */ +public class BaseTest { + protected static final String NAME_SERVER_LIST = "10.232.26.122:9876"; + protected static BrokerController brokerController; + protected String instanceName = "qatest-" + new Exception().getStackTrace()[1].getClassName(); + protected String[] tags = new String[] { "TagA", "TagB", "TagC", "TagD", "TagE" }; + + + @BeforeClass + public static void setUpBeforeClass() throws Exception { + if (StringUtils.isNotBlank(NAME_SERVER_LIST)) { + System.setProperty(MixAll.NAMESRV_ADDR_PROPERTY, NAME_SERVER_LIST); + } + else { + initNameServerAndBroker(); + } + } + + + // 初始化nameserver & broker + public static void initNameServerAndBroker() throws Exception { + // 设置当前程序版本号,每次发布版本时,都要修改CurrentVersion + System.setProperty(RemotingCommand.RemotingVersionKey, Integer.toString(MQVersion.CurrentVersion)); + try { + // 初始化配置文件 + final BrokerConfig brokerConfig = new BrokerConfig(); + final NettyServerConfig nettyServerConfig = new NettyServerConfig(); + nettyServerConfig.setListenPort(10911); + final MessageStoreConfig messageStoreConfig = new MessageStoreConfig(); + // 清理环境 + // deleteDir(System.getProperty("user.home") + File.separator + + // "store"); + + if (null == brokerConfig.getRocketmqHome()) { + System.out.println("Please set the " + MixAll.ROCKETMQ_HOME_ENV + + " variable in your environment to match the location of the RocketMQ installation"); + System.exit(-2); + } + + // BrokerId的处理 + switch (messageStoreConfig.getBrokerRole()) { + case ASYNC_MASTER: + case SYNC_MASTER: + // Master Id必须是0 + brokerConfig.setBrokerId(MixAll.MASTER_ID); + break; + case SLAVE: + // Slave Id由Slave监听IP、端口决定 + long id = + MixAll.createBrokerId(brokerConfig.getBrokerIP1(), nettyServerConfig.getListenPort()); + brokerConfig.setBrokerId(id); + break; + default: + break; + } + + // Master监听Slave请求的端口,默认为服务端口+1 + messageStoreConfig.setHaListenPort(nettyServerConfig.getListenPort() + 1); + + // 初始化Logback + LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory(); + JoranConfigurator configurator = new JoranConfigurator(); + configurator.setContext(lc); + lc.reset(); + configurator.doConfigure(brokerConfig.getRocketmqHome() + "/conf/log4j_broker.xml"); + final Logger log = LoggerFactory.getLogger(LoggerName.BrokerLoggerName); + + // 打印启动参数 + MixAll.printObjectProperties(log, brokerConfig); + MixAll.printObjectProperties(log, nettyServerConfig); + MixAll.printObjectProperties(log, messageStoreConfig); + + // 初始化服务控制对象 + brokerController = + new BrokerController(brokerConfig, nettyServerConfig, new NettyClientConfig(), + messageStoreConfig); + boolean initResult = brokerController.initialize(); + if (!initResult) { + brokerController.shutdown(); + System.exit(-3); + } + + Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() { + private volatile boolean hasShutdown = false; + private AtomicInteger shutdownTimes = new AtomicInteger(0); + + + @Override + public void run() { + synchronized (this) { + log.info("shutdown hook was invoked, " + this.shutdownTimes.incrementAndGet()); + if (!this.hasShutdown) { + this.hasShutdown = true; + long begineTime = System.currentTimeMillis(); + brokerController.shutdown(); + long consumingTimeTotal = System.currentTimeMillis() - begineTime; + log.info("shutdown hook over, consuming time total(ms): " + consumingTimeTotal); + } + } + } + }, "ShutdownHook")); + + // 启动服务控制对象 + brokerController.start(); + String tip = + "The broker[" + brokerController.getBrokerConfig().getBrokerName() + ", " + + brokerController.getBrokerAddr() + "] boot success."; + log.info(tip); + System.out.println(tip); + } + catch (Throwable e) { + e.printStackTrace(); + System.exit(-1); + } + } + + + @AfterClass + public static void tearDown() throws Exception { + if (brokerController != null) { + brokerController.shutdown(); + } + } + + + public String getTagsExpression(int count) { + if (count == 0) { + return "*"; + } + else { + StringBuilder sb = new StringBuilder(); + String splitor = ""; + Random random = new Random(); + for (int i = 0; i < count; i++) { + sb.append(tags[random.nextInt(tags.length)]); + sb.append(splitor); + splitor = " || "; + } + return sb.toString(); + } + + } + + + public static void deleteDir(String path) { + File file = new File(path); + if (file.exists()) { + if (file.isDirectory()) { + File[] files = file.listFiles(); + for (File subFile : files) { + if (subFile.isDirectory()) + deleteDir(subFile.getPath()); + else + subFile.delete(); + } + } + file.delete(); + } + } +} diff --git a/rocketmq-qatest/src/test/java/com/alibaba/rocketmq/test/integration/benchmark/BenchmarkBaseTest.java b/rocketmq-qatest/src/test/java/com/alibaba/rocketmq/test/integration/benchmark/BenchmarkBaseTest.java new file mode 100644 index 00000000..f3994115 --- /dev/null +++ b/rocketmq-qatest/src/test/java/com/alibaba/rocketmq/test/integration/benchmark/BenchmarkBaseTest.java @@ -0,0 +1,46 @@ +package com.alibaba.rocketmq.test.integration.benchmark; + +import org.apache.commons.lang.StringUtils; + +import com.alibaba.rocketmq.common.MixAll; +import com.alibaba.rocketmq.common.message.Message; +import com.alibaba.rocketmq.test.integration.BaseTest; + + +/** + * @author manhong.yqd + * @since 2013-8-26 + */ +public class BenchmarkBaseTest extends BaseTest { + protected String consumerGroup = "qatest_Benchmark_consumer"; + protected String producerGroup = "qatest_Benchmark_producer"; + protected String topic = "qatest_BenchmarkTest"; + static { + if (StringUtils.isNotBlank(NAME_SERVER_LIST)) { + System.setProperty(MixAll.NAMESRV_ADDR_PROPERTY, NAME_SERVER_LIST); + } + else { + try { + initNameServerAndBroker(); + } + catch (Exception e) { + e.printStackTrace(); + } + } + } + + + protected static Message buildMessage(final int messageSize) { + Message msg = new Message(); + msg.setTopic("BenchmarkTest"); + + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < messageSize; i += 10) { + sb.append("hello baby"); + } + + msg.setBody(sb.toString().getBytes()); + + return msg; + } +} diff --git a/rocketmq-qatest/src/test/java/com/alibaba/rocketmq/test/integration/benchmark/InOneProducerTest.java b/rocketmq-qatest/src/test/java/com/alibaba/rocketmq/test/integration/benchmark/InOneProducerTest.java new file mode 100644 index 00000000..04f21c10 --- /dev/null +++ b/rocketmq-qatest/src/test/java/com/alibaba/rocketmq/test/integration/benchmark/InOneProducerTest.java @@ -0,0 +1,151 @@ +/** + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.rocketmq.test.integration.benchmark; + +import java.util.LinkedList; +import java.util.Timer; +import java.util.TimerTask; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +import com.alibaba.rocketmq.client.exception.MQBrokerException; +import com.alibaba.rocketmq.client.exception.MQClientException; +import com.alibaba.rocketmq.client.producer.DefaultMQProducer; +import com.alibaba.rocketmq.common.message.Message; +import com.alibaba.rocketmq.remoting.exception.RemotingException; + + +/** + * 性能测试,多线程同一个 producer 同步发送消息 + */ +public class InOneProducerTest extends BenchmarkBaseTest { + + public static void main(String[] args) { + final int threadCount = args.length >= 1 ? Integer.parseInt(args[0]) : 32; + final int messageSize = args.length >= 2 ? Integer.parseInt(args[1]) : 256; + + System.out.printf("threadCount %d messageSize %d\n", threadCount, messageSize); + + final Message msg = buildMessage(messageSize); + + final ExecutorService sendThreadPool = Executors.newFixedThreadPool(threadCount); + + final StatsBenchmarkProducer statsBenchmark = new StatsBenchmarkProducer(); + + final Timer timer = new Timer("BenchmarkTimerThread", true); + + final LinkedList snapshotList = new LinkedList(); + + timer.scheduleAtFixedRate(new TimerTask() { + @Override + public void run() { + snapshotList.addLast(statsBenchmark.createSnapshot()); + if (snapshotList.size() > 10) { + snapshotList.removeFirst(); + } + } + }, 1000, 1000); + + timer.scheduleAtFixedRate(new TimerTask() { + private void printStats() { + if (snapshotList.size() >= 10) { + Long[] begin = snapshotList.getFirst(); + Long[] end = snapshotList.getLast(); + + final long sendTps = + (long) (((end[3] - begin[3]) / (double) (end[0] - begin[0])) * 1000L); + final double averageRT = ((end[5] - begin[5]) / (double) (end[3] - begin[3])); + + System.out.printf( + "Send TPS: %d Max RT: %d Average RT: %7.3f Send Failed: %d Response Failed: %d\n"// + , sendTps// + , statsBenchmark.getSendMessageMaxRT().get()// + , averageRT// + , end[2]// + , end[4]// + ); + } + } + + + @Override + public void run() { + try { + this.printStats(); + } + catch (Exception e) { + e.printStackTrace(); + } + } + }, 10000, 10000); + + final DefaultMQProducer producer = new DefaultMQProducer("benchmark_producer"); + + producer.setCompressMsgBodyOverHowmuch(Integer.MAX_VALUE); + + try { + producer.start(); + for (int i = 0; i < threadCount; i++) { + sendThreadPool.execute(new Runnable() { + @Override + public void run() { + while (true) { + try { + final long beginTimestamp = System.currentTimeMillis(); + producer.send(msg); + statsBenchmark.getSendRequestSuccessCount().incrementAndGet(); + statsBenchmark.getReceiveResponseSuccessCount().incrementAndGet(); + final long currentRT = System.currentTimeMillis() - beginTimestamp; + statsBenchmark.getSendMessageSuccessTimeTotal().addAndGet(currentRT); + long prevMaxRT = statsBenchmark.getSendMessageMaxRT().get(); + while (currentRT > prevMaxRT) { + boolean updated = + statsBenchmark.getSendMessageMaxRT().compareAndSet(prevMaxRT, + currentRT); + if (updated) + break; + + prevMaxRT = statsBenchmark.getSendMessageMaxRT().get(); + } + } + catch (RemotingException e) { + statsBenchmark.getSendRequestFailedCount().incrementAndGet(); + e.printStackTrace(); + } + catch (InterruptedException e) { + statsBenchmark.getSendRequestFailedCount().incrementAndGet(); + e.printStackTrace(); + } + catch (MQClientException e) { + statsBenchmark.getSendRequestFailedCount().incrementAndGet(); + e.printStackTrace(); + } + catch (MQBrokerException e) { + statsBenchmark.getReceiveResponseFailedCount().incrementAndGet(); + e.printStackTrace(); + } + } + } + }); + } + } + catch (MQClientException e) { + e.printStackTrace(); // To change body of catch statement use File | + // Settings | File Templates. + } + + } +} diff --git a/rocketmq-qatest/src/test/java/com/alibaba/rocketmq/test/integration/benchmark/ManyProducerTest.java b/rocketmq-qatest/src/test/java/com/alibaba/rocketmq/test/integration/benchmark/ManyProducerTest.java new file mode 100644 index 00000000..9b19e53f --- /dev/null +++ b/rocketmq-qatest/src/test/java/com/alibaba/rocketmq/test/integration/benchmark/ManyProducerTest.java @@ -0,0 +1,150 @@ +/** + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.rocketmq.test.integration.benchmark; + +import java.util.LinkedList; +import java.util.Timer; +import java.util.TimerTask; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +import com.alibaba.rocketmq.client.exception.MQBrokerException; +import com.alibaba.rocketmq.client.exception.MQClientException; +import com.alibaba.rocketmq.client.producer.DefaultMQProducer; +import com.alibaba.rocketmq.common.message.Message; +import com.alibaba.rocketmq.remoting.exception.RemotingException; + + +/** + * 性能测试,多线程多个 producer 同步发送消息 + * + * @author: manhong.yqd + * @since: 13-9-5 + */ +public class ManyProducerTest extends BenchmarkBaseTest { + + public static void main(String[] args) { + final int threadCount = args.length >= 1 ? Integer.parseInt(args[0]) : 300; + final int messageSize = args.length >= 2 ? Integer.parseInt(args[1]) : 256; + + System.out.printf("threadCount %d messageSize %d\n", threadCount, messageSize); + + final Message msg = buildMessage(messageSize); + + final ExecutorService sendThreadPool = Executors.newFixedThreadPool(threadCount); + + final StatsBenchmarkProducer statsBenchmark = new StatsBenchmarkProducer(); + + final Timer timer = new Timer("BenchmarkTimerThread", true); + + final LinkedList snapshotList = new LinkedList(); + + timer.scheduleAtFixedRate(new TimerTask() { + @Override + public void run() { + snapshotList.addLast(statsBenchmark.createSnapshot()); + if (snapshotList.size() > 10) { + snapshotList.removeFirst(); + } + } + }, 1000, 1000); + + timer.scheduleAtFixedRate(new TimerTask() { + private void printStats() { + if (snapshotList.size() >= 10) { + Long[] begin = snapshotList.getFirst(); + Long[] end = snapshotList.getLast(); + + final long sendTps = + (long) (((end[3] - begin[3]) / (double) (end[0] - begin[0])) * 1000L); + final double averageRT = ((end[5] - begin[5]) / (double) (end[3] - begin[3])); + + System.out.printf( + "Send TPS: %d Max RT: %d Average RT: %7.3f Send Failed: %d Response Failed: %d\n"// + , sendTps// + , statsBenchmark.getSendMessageMaxRT().get()// + , averageRT// + , end[2]// + , end[4]// + ); + } + } + + + @Override + public void run() { + try { + this.printStats(); + } + catch (Exception e) { + e.printStackTrace(); + } + } + }, 10000, 10000); + + final String instanceName = "ins." + System.currentTimeMillis(); + for (int i = 0; i < threadCount; i++) { + final int index = i; + sendThreadPool.execute(new Runnable() { + @Override + public void run() { + try { + final DefaultMQProducer producer = + new DefaultMQProducer("benchmark_producer" + index); + producer.setCompressMsgBodyOverHowmuch(Integer.MAX_VALUE); + producer.setInstanceName(instanceName); + producer.start(); + + while (true) { + final long beginTimestamp = System.currentTimeMillis(); + producer.send(msg); + statsBenchmark.getSendRequestSuccessCount().incrementAndGet(); + statsBenchmark.getReceiveResponseSuccessCount().incrementAndGet(); + final long currentRT = System.currentTimeMillis() - beginTimestamp; + statsBenchmark.getSendMessageSuccessTimeTotal().addAndGet(currentRT); + long prevMaxRT = statsBenchmark.getSendMessageMaxRT().get(); + while (currentRT > prevMaxRT) { + boolean updated = + statsBenchmark.getSendMessageMaxRT().compareAndSet(prevMaxRT, + currentRT); + if (updated) + break; + + prevMaxRT = statsBenchmark.getSendMessageMaxRT().get(); + } + } + } + catch (RemotingException e) { + statsBenchmark.getSendRequestFailedCount().incrementAndGet(); + e.printStackTrace(); + } + catch (InterruptedException e) { + statsBenchmark.getSendRequestFailedCount().incrementAndGet(); + e.printStackTrace(); + } + catch (MQClientException e) { + statsBenchmark.getSendRequestFailedCount().incrementAndGet(); + e.printStackTrace(); + } + catch (MQBrokerException e) { + statsBenchmark.getReceiveResponseFailedCount().incrementAndGet(); + e.printStackTrace(); + } + } + }); + } + } +} diff --git a/rocketmq-qatest/src/test/java/com/alibaba/rocketmq/test/integration/benchmark/StatsBenchmarkProducer.java b/rocketmq-qatest/src/test/java/com/alibaba/rocketmq/test/integration/benchmark/StatsBenchmarkProducer.java new file mode 100644 index 00000000..ae49ce39 --- /dev/null +++ b/rocketmq-qatest/src/test/java/com/alibaba/rocketmq/test/integration/benchmark/StatsBenchmarkProducer.java @@ -0,0 +1,69 @@ +package com.alibaba.rocketmq.test.integration.benchmark; + +import java.util.concurrent.atomic.AtomicLong; + + +/** + * description + * + * @author: manhong.yqd + * @since: 13-9-5 + */ +public class StatsBenchmarkProducer { + // 1 + private final AtomicLong sendRequestSuccessCount = new AtomicLong(0L); + // 2 + private final AtomicLong sendRequestFailedCount = new AtomicLong(0L); + // 3 + private final AtomicLong receiveResponseSuccessCount = new AtomicLong(0L); + // 4 + private final AtomicLong receiveResponseFailedCount = new AtomicLong(0L); + // 5 + private final AtomicLong sendMessageSuccessTimeTotal = new AtomicLong(0L); + // 6 + private final AtomicLong sendMessageMaxRT = new AtomicLong(0L); + + + public Long[] createSnapshot() { + Long[] snap = new Long[] {// + System.currentTimeMillis(),// + this.sendRequestSuccessCount.get(),// + this.sendRequestFailedCount.get(),// + this.receiveResponseSuccessCount.get(),// + this.receiveResponseFailedCount.get(),// + this.sendMessageSuccessTimeTotal.get(), // + }; + + return snap; + } + + + public AtomicLong getSendRequestSuccessCount() { + return sendRequestSuccessCount; + } + + + public AtomicLong getSendRequestFailedCount() { + return sendRequestFailedCount; + } + + + public AtomicLong getReceiveResponseSuccessCount() { + return receiveResponseSuccessCount; + } + + + public AtomicLong getReceiveResponseFailedCount() { + return receiveResponseFailedCount; + } + + + public AtomicLong getSendMessageSuccessTimeTotal() { + return sendMessageSuccessTimeTotal; + } + + + public AtomicLong getSendMessageMaxRT() { + return sendMessageMaxRT; + } +} diff --git a/rocketmq-qatest/src/test/java/com/alibaba/rocketmq/test/integration/normal/NormalBaseTest.java b/rocketmq-qatest/src/test/java/com/alibaba/rocketmq/test/integration/normal/NormalBaseTest.java new file mode 100644 index 00000000..cde1782f --- /dev/null +++ b/rocketmq-qatest/src/test/java/com/alibaba/rocketmq/test/integration/normal/NormalBaseTest.java @@ -0,0 +1,14 @@ +package com.alibaba.rocketmq.test.integration.normal; + +import com.alibaba.rocketmq.test.integration.BaseTest; + + +/** + * @author manhong.yqd + * @since 2013-8-26 + */ +public class NormalBaseTest extends BaseTest { + protected String consumerGroup = "qatest_consumer"; + protected String producerGroup = "qatest_producer"; + protected String topic = "qatest_TopicTest"; +} diff --git a/rocketmq-qatest/src/test/java/com/alibaba/rocketmq/test/integration/normal/ProducerTest.java b/rocketmq-qatest/src/test/java/com/alibaba/rocketmq/test/integration/normal/ProducerTest.java new file mode 100644 index 00000000..3f62b299 --- /dev/null +++ b/rocketmq-qatest/src/test/java/com/alibaba/rocketmq/test/integration/normal/ProducerTest.java @@ -0,0 +1,62 @@ +/** + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.rocketmq.test.integration.normal; + +import org.junit.Before; +import org.junit.Test; + +import com.alibaba.rocketmq.client.exception.MQClientException; +import com.alibaba.rocketmq.client.producer.DefaultMQProducer; +import com.alibaba.rocketmq.client.producer.SendResult; +import com.alibaba.rocketmq.common.message.Message; + + +/** + * @author manhong.yqd + * @since 2013-8-26 + */ +public class ProducerTest extends NormalBaseTest { + private DefaultMQProducer producer; + + + @Before + public void before() throws Exception { + producer = new DefaultMQProducer(producerGroup); + producer.setInstanceName(instanceName); + producer.start(); + } + + + @Test + public void producerTest() throws MQClientException, InterruptedException { + for (int i = 0; i < 1000; i++) { + try { + Message msg = new Message(topic,// topic + tags[i % tags.length],// tag + "KEY" + i,// key + ("Hello RocketMQ " + i).getBytes()// body + ); + SendResult sendResult = producer.send(msg); + System.out.println(sendResult); + } + catch (Exception e) { + e.printStackTrace(); + Thread.sleep(1000); + } + } + producer.shutdown(); + } +} diff --git a/rocketmq-qatest/src/test/java/com/alibaba/rocketmq/test/integration/normal/PullConsumerTest.java b/rocketmq-qatest/src/test/java/com/alibaba/rocketmq/test/integration/normal/PullConsumerTest.java new file mode 100644 index 00000000..c659669a --- /dev/null +++ b/rocketmq-qatest/src/test/java/com/alibaba/rocketmq/test/integration/normal/PullConsumerTest.java @@ -0,0 +1,177 @@ +package com.alibaba.rocketmq.test.integration.normal; + +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.nio.ByteBuffer; +import java.util.Set; +import java.util.concurrent.TimeUnit; + +import org.apache.commons.lang.StringUtils; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import com.alibaba.rocketmq.client.consumer.DefaultMQPullConsumer; +import com.alibaba.rocketmq.client.consumer.MessageQueueListener; +import com.alibaba.rocketmq.client.consumer.PullResult; +import com.alibaba.rocketmq.client.exception.MQBrokerException; +import com.alibaba.rocketmq.client.exception.MQClientException; +import com.alibaba.rocketmq.common.message.MessageDecoder; +import com.alibaba.rocketmq.common.message.MessageExt; +import com.alibaba.rocketmq.common.message.MessageQueue; +import com.alibaba.rocketmq.common.protocol.heartbeat.MessageModel; +import com.alibaba.rocketmq.remoting.exception.RemotingException; + + +/** + * @author manhong.yqd + * @since 2013-8-26 + */ +public class PullConsumerTest extends NormalBaseTest { + private DefaultMQPullConsumer consumer; + + + @Before + public void before() throws Exception { + consumer = initConsumer(null); + } + + + /** + * 消费广播消息 + * + * @throws com.alibaba.rocketmq.client.exception.MQClientException + * @throws com.alibaba.rocketmq.remoting.exception.RemotingException + * @throws com.alibaba.rocketmq.client.exception.MQBrokerException + * @throws InterruptedException + */ + @Test + public void broadCastMessage() throws MQClientException, RemotingException, MQBrokerException, + InterruptedException { + consumer.start(); + + Set mqs = consumer.fetchSubscribeMessageQueues(topic); + System.out.println("mqs:" + mqs.size()); + + while (true) { + for (MessageQueue mq : mqs) { + PullResult pullResult = + consumer.pullBlockIfNotFound(mq, null, getMessageQueueOffset(mq, false), 10); + putMessageQueueOffset(mq, pullResult.getNextBeginOffset()); + firePullResult(pullResult); + } + TimeUnit.SECONDS.sleep(2); + } + } + + + /** + * 消费集群消息 + * + * @throws com.alibaba.rocketmq.client.exception.MQClientException + * @throws com.alibaba.rocketmq.remoting.exception.RemotingException + * @throws InterruptedException + * @throws com.alibaba.rocketmq.client.exception.MQBrokerException + */ + @Test + public void clusterMessage() throws MQClientException, RemotingException, InterruptedException, + MQBrokerException { + consumer.setMessageModel(MessageModel.CLUSTERING); + consumer.start(); + while (true) { + Set mqs = consumer.fetchMessageQueuesInBalance(topic); + System.out.println("mqs:" + mqs.size()); + for (MessageQueue mq : mqs) { + PullResult pullResult = consumer.pull(mq, null, getMessageQueueOffset(mq, false), 10); + putMessageQueueOffset(mq, pullResult.getNextBeginOffset()); + firePullResult(pullResult); + } + TimeUnit.SECONDS.sleep(2); + } + } + + + @Test + // 根据消息ID查询消息 + public void searchByMessageId() throws MQClientException, RemotingException, MQBrokerException, + InterruptedException, UnknownHostException { + ByteBuffer byteBufferMsgId = ByteBuffer.allocate(MessageDecoder.MSG_ID_LENGTH); + ByteBuffer addr = ByteBuffer.allocate(8); + addr.put(InetAddress.getByName("10.232.25.81").getAddress()); + addr.putInt(10911); + long offset = 0; + while (true) { + Set mqs = consumer.fetchMessageQueuesInBalance(topic); + System.out.println("mqs:" + mqs.size()); + for (MessageQueue mq : mqs) { + addr.flip(); + String msgId = MessageDecoder.createMessageId(byteBufferMsgId, addr, 1); + MessageExt data = consumer.viewMessage(msgId); + System.out.println(data); + } + TimeUnit.SECONDS.sleep(2); + } + } + + + @After + public void after() throws Exception { + consumer.shutdown(); + Thread.sleep(2000); + } + + + private void firePullResult(PullResult pullResult) { + switch (pullResult.getPullStatus()) { + case FOUND: + for (MessageExt mex : pullResult.getMsgFoundList()) { + System.out.println(mex); + } + break; + case NO_MATCHED_MSG: + break; + case NO_NEW_MSG: + break; + case OFFSET_ILLEGAL: + break; + default: + break; + } + } + + + private void putMessageQueueOffset(MessageQueue mq, long offset) throws MQClientException { + consumer.updateConsumeOffset(mq, offset); + } + + + private long getMessageQueueOffset(MessageQueue mq, boolean fromStore) throws MQClientException { + long offset = consumer.fetchConsumeOffset(mq, fromStore); + offset = (offset < 0 ? 0 : offset); + System.out.println("offset:" + offset); + return offset; + } + + + private DefaultMQPullConsumer initConsumer(String _instanceName) throws MQClientException, + InterruptedException { + DefaultMQPullConsumer consumer = new DefaultMQPullConsumer(consumerGroup); + if (StringUtils.isNotBlank(_instanceName)) { + consumer.setInstanceName(_instanceName); + } + else { + consumer.setInstanceName(instanceName); + } + MessageQueueListener listener = new MessageQueueListener() { + @Override + public void messageQueueChanged(String topic, Set mqAll, Set mqDivided) { + System.out.println("Topic=" + topic); + System.out.println("mqAll:" + mqAll); + System.out.println("mqDivided:" + mqDivided); + } + }; + consumer.registerMessageQueueListener(topic, listener); + Thread.sleep(2000); + return consumer; + } +} diff --git a/rocketmq-qatest/src/test/java/com/alibaba/rocketmq/test/integration/normal/PushConsumerTest.java b/rocketmq-qatest/src/test/java/com/alibaba/rocketmq/test/integration/normal/PushConsumerTest.java new file mode 100644 index 00000000..17425007 --- /dev/null +++ b/rocketmq-qatest/src/test/java/com/alibaba/rocketmq/test/integration/normal/PushConsumerTest.java @@ -0,0 +1,116 @@ +package com.alibaba.rocketmq.test.integration.normal; + +import java.io.IOException; +import java.util.List; +import java.util.concurrent.atomic.AtomicLong; + +import org.junit.Before; +import org.junit.Test; + +import com.alibaba.rocketmq.client.consumer.DefaultMQPushConsumer; +import com.alibaba.rocketmq.client.consumer.listener.ConsumeConcurrentlyContext; +import com.alibaba.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus; +import com.alibaba.rocketmq.client.consumer.listener.MessageListener; +import com.alibaba.rocketmq.client.consumer.listener.MessageListenerConcurrently; +import com.alibaba.rocketmq.client.exception.MQClientException; +import com.alibaba.rocketmq.common.consumer.ConsumeFromWhere; +import com.alibaba.rocketmq.common.message.MessageExt; +import com.alibaba.rocketmq.common.protocol.heartbeat.MessageModel; + + +/** + * @author manhong.yqd + * @since 2013-8-26 + */ +public class PushConsumerTest extends NormalBaseTest { + private DefaultMQPushConsumer consumer; + + + @Before + public void before() throws Exception { + consumer = new DefaultMQPushConsumer(consumerGroup); + consumer.setInstanceName(instanceName + System.nanoTime()); + consumer.subscribe(topic, getTagsExpression(0)); + // consumer.subscribe(topic, getTagsExpression(3)); + } + + + @Test + public void pushConsumerFromLastOffset() throws MQClientException { + consumer.setMessageModel(MessageModel.CLUSTERING); + consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_LAST_OFFSET); + MessageListener listener = createMessageListener(); + consumer.registerMessageListener(listener); + + consumer.start(); + System.out.println("Consumer Started."); + try { + System.in.read(); + } + catch (IOException e) { + e.printStackTrace(); + } + } + + + @Test + public void pushConsumerFromMinOffset() throws MQClientException { + consumer.setMessageModel(MessageModel.CLUSTERING); + consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_FIRST_OFFSET); + MessageListener listener = createMessageListener(); + consumer.registerMessageListener(listener); + + consumer.start(); + System.out.println("Consumer Started."); + try { + System.in.read(); + } + catch (IOException e) { + e.printStackTrace(); + } + } + + + @Test + public void pushConsumerByBroadCast() throws MQClientException { + consumer.setMessageModel(MessageModel.BROADCASTING); + MessageListener listener = createMessageListener(); + consumer.registerMessageListener(listener); + + consumer.start(); + System.out.println("Consumer Started."); + try { + System.in.read(); + } + catch (IOException e) { + e.printStackTrace(); + } + } + + + private MessageListener createMessageListener() { + return new MessageListenerConcurrently() { + AtomicLong consumeTimes = new AtomicLong(0); + + + @Override + public ConsumeConcurrentlyStatus consumeMessage(List msgs, + ConsumeConcurrentlyContext context) { + + this.consumeTimes.incrementAndGet(); + if ((this.consumeTimes.get() % 11) == 0) { + System.out.println("Delay 0========Receive New Messages: " + msgs); + return ConsumeConcurrentlyStatus.RECONSUME_LATER; + } + else if ((this.consumeTimes.get() % 22) == 0) { + System.out.println(Thread.currentThread().getName() + + "Delay 5========Receive New Messages: " + msgs); + context.setDelayLevelWhenNextConsume(5); + return ConsumeConcurrentlyStatus.RECONSUME_LATER; + } + System.out.println("No Delay========Receive New Messages: " + msgs); + return ConsumeConcurrentlyStatus.CONSUME_SUCCESS; + } + }; + } +} diff --git a/rocketmq-qatest/src/test/java/com/alibaba/rocketmq/test/integration/order/OrderBaseTest.java b/rocketmq-qatest/src/test/java/com/alibaba/rocketmq/test/integration/order/OrderBaseTest.java new file mode 100644 index 00000000..cf845f19 --- /dev/null +++ b/rocketmq-qatest/src/test/java/com/alibaba/rocketmq/test/integration/order/OrderBaseTest.java @@ -0,0 +1,14 @@ +package com.alibaba.rocketmq.test.integration.order; + +import com.alibaba.rocketmq.test.integration.BaseTest; + + +/** + * @author manhong.yqd + * @since 2013-8-26 + */ +public class OrderBaseTest extends BaseTest { + protected String consumerGroup = "qatest_consumer_order"; + protected String producerGroup = "qatest_producer_order"; + protected String topic = "qatest_TopicTest_order"; +} diff --git a/rocketmq-qatest/src/test/java/com/alibaba/rocketmq/test/integration/order/ProducerTest.java b/rocketmq-qatest/src/test/java/com/alibaba/rocketmq/test/integration/order/ProducerTest.java new file mode 100644 index 00000000..3a55163c --- /dev/null +++ b/rocketmq-qatest/src/test/java/com/alibaba/rocketmq/test/integration/order/ProducerTest.java @@ -0,0 +1,55 @@ +package com.alibaba.rocketmq.test.integration.order; + +import java.util.List; + +import org.junit.Before; +import org.junit.Test; + +import com.alibaba.rocketmq.client.exception.MQBrokerException; +import com.alibaba.rocketmq.client.exception.MQClientException; +import com.alibaba.rocketmq.client.producer.DefaultMQProducer; +import com.alibaba.rocketmq.client.producer.MessageQueueSelector; +import com.alibaba.rocketmq.client.producer.SendResult; +import com.alibaba.rocketmq.common.message.Message; +import com.alibaba.rocketmq.common.message.MessageQueue; +import com.alibaba.rocketmq.remoting.exception.RemotingException; + + +/** + * @author manhong.yqd + * @since 2013-8-26 + */ +public class ProducerTest extends OrderBaseTest { + private DefaultMQProducer producer; + + + @Before + public void before() { + producer = new DefaultMQProducer(producerGroup); + producer.setInstanceName(instanceName); + } + + + @Test + public void producerTest() throws MQClientException, RemotingException, InterruptedException, + MQBrokerException { + producer.start(); + for (int i = 0; i < 10; i++) { + // 订单ID相同的消息要有序 + // int orderId = i % 10; + int orderId = 0; + Message msg = + new Message(topic, tags[i % tags.length], "KEY" + i, ("Hello RocketMQ " + i).getBytes()); + SendResult result = producer.send(msg, new MessageQueueSelector() { + @Override + public MessageQueue select(List mqs, Message msg, Object arg) { + Integer id = (Integer) arg; + int index = id % mqs.size(); + return mqs.get(index); + } + }, orderId); + System.out.println(result); + } + producer.shutdown(); + } +} diff --git a/rocketmq-qatest/src/test/java/com/alibaba/rocketmq/test/integration/order/PushConsumerTest.java b/rocketmq-qatest/src/test/java/com/alibaba/rocketmq/test/integration/order/PushConsumerTest.java new file mode 100644 index 00000000..37e1c18f --- /dev/null +++ b/rocketmq-qatest/src/test/java/com/alibaba/rocketmq/test/integration/order/PushConsumerTest.java @@ -0,0 +1,173 @@ +/** + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.rocketmq.test.integration.order; + +import java.io.IOException; +import java.util.List; +import java.util.concurrent.atomic.AtomicLong; + +import org.junit.Before; +import org.junit.Test; + +import com.alibaba.rocketmq.client.consumer.DefaultMQPushConsumer; +import com.alibaba.rocketmq.client.consumer.listener.ConsumeOrderlyContext; +import com.alibaba.rocketmq.client.consumer.listener.ConsumeOrderlyStatus; +import com.alibaba.rocketmq.client.consumer.listener.MessageListener; +import com.alibaba.rocketmq.client.consumer.listener.MessageListenerOrderly; +import com.alibaba.rocketmq.client.exception.MQClientException; +import com.alibaba.rocketmq.common.consumer.ConsumeFromWhere; +import com.alibaba.rocketmq.common.message.MessageExt; +import com.alibaba.rocketmq.common.protocol.heartbeat.MessageModel; + + +/** + * 顺序消息消费,带事务方式(应用可控制Offset什么时候提交) + * + * @author manhong.yqd + * @since 2013-8-26 + */ +public class PushConsumerTest extends OrderBaseTest { + private DefaultMQPushConsumer consumer; + + + @Before + public void before() throws Exception { + consumer = new DefaultMQPushConsumer(consumerGroup); + consumer.setInstanceName(instanceName + System.nanoTime()); + consumer.subscribe(topic, getTagsExpression(0)); + // consumer.subscribe(topic, getTagsExpression(3)); + } + + + @Test + public void pushConsumerFromLastOffset() throws MQClientException { + consumer.setMessageModel(MessageModel.CLUSTERING); + consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_LAST_OFFSET); + MessageListener listener = getRollBackMessageListener(); + consumer.registerMessageListener(listener); + + consumer.start(); + System.out.println("Consumer Started."); + try { + System.in.read(); + } + catch (IOException e) { + e.printStackTrace(); + } + } + + + @Test + public void pushConsumerWithAutoCommitFromLastOffset() throws MQClientException { + consumer.setMessageModel(MessageModel.CLUSTERING); + consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_LAST_OFFSET); + MessageListener listener = getAutoCommitMessageListener(); + consumer.registerMessageListener(listener); + + consumer.start(); + System.out.println("Consumer Started."); + try { + System.in.read(); + } + catch (IOException e) { + e.printStackTrace(); + } + } + + + @Test + public void pushConsumerWithAutoCommitFromMinOffset() throws MQClientException { + consumer.setMessageModel(MessageModel.CLUSTERING); + consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_FIRST_OFFSET); + MessageListener listener = getAutoCommitMessageListener(); + consumer.registerMessageListener(listener); + + consumer.start(); + System.out.println("Consumer Started."); + try { + System.in.read(); + } + catch (IOException e) { + e.printStackTrace(); + } + } + + + private static MessageListenerOrderly getRollBackMessageListener() { + return new MessageListenerOrderly() { + AtomicLong consumeTimes = new AtomicLong(0); + + + @Override + public ConsumeOrderlyStatus consumeMessage(List msgs, ConsumeOrderlyContext context) { + System.out.println("MESSAGE BODY========" + new String(msgs.get(0).getBody())); + context.setAutoCommit(false); + this.consumeTimes.incrementAndGet(); + if ((this.consumeTimes.get() % 1) == 0) { + System.out.println("SUCCESS========Receive New Messages: " + msgs); + return ConsumeOrderlyStatus.SUCCESS; + } + else if ((this.consumeTimes.get() % 2) == 0) { + System.out.println("ROLLBACK========Receive New Messages: " + msgs); + return ConsumeOrderlyStatus.ROLLBACK; + } + else if ((this.consumeTimes.get() % 3) == 0) { + System.out.println("COMMIT========Receive New Messages: " + msgs); + return ConsumeOrderlyStatus.COMMIT; + } + else if ((this.consumeTimes.get() % 5) == 0) { + System.out.println("SUSPEND_CURRENT_QUEUE_A_MOMENT========Receive New Messages: " + + msgs.get(0)); + context.setSuspendCurrentQueueTimeMillis(3000); + return ConsumeOrderlyStatus.SUSPEND_CURRENT_QUEUE_A_MOMENT; + } + + return ConsumeOrderlyStatus.SUCCESS; + } + }; + } + + + private static MessageListenerOrderly getAutoCommitMessageListener() { + return new MessageListenerOrderly() { + AtomicLong consumeTimes = new AtomicLong(0); + + + @Override + public ConsumeOrderlyStatus consumeMessage(List msgs, ConsumeOrderlyContext context) { + System.out.println("MESSAGE BODY========" + new String(msgs.get(0).getBody())); + this.consumeTimes.incrementAndGet(); + if ((this.consumeTimes.get() % 1) == 0) { + System.out.println("SUCCESS========Receive New Messages: " + msgs); + return ConsumeOrderlyStatus.SUCCESS; + } + else if ((this.consumeTimes.get() % 2) == 0) { + System.out.println("ROLLBACK========Receive New Messages: " + msgs); + return ConsumeOrderlyStatus.ROLLBACK; + } + else if ((this.consumeTimes.get() % 5) == 0) { + System.out.println("SUSPEND_CURRENT_QUEUE_A_MOMENT========Receive New Messages: " + + msgs.get(0)); + context.setSuspendCurrentQueueTimeMillis(3000); + return ConsumeOrderlyStatus.SUSPEND_CURRENT_QUEUE_A_MOMENT; + } + + return ConsumeOrderlyStatus.SUCCESS; + } + }; + } + +} diff --git a/rocketmq-remoting/pom.xml b/rocketmq-remoting/pom.xml index 830c9d31..2ebabfd5 100644 --- a/rocketmq-remoting/pom.xml +++ b/rocketmq-remoting/pom.xml @@ -1,14 +1,12 @@ - + com.alibaba.rocketmq rocketmq-all - 3.0.0-SNAPSHOT + 3.0.8-SNAPSHOT 4.0.0 jar - com.alibaba.rocketmq rocketmq-remoting rocketmq-remoting ${project.version} @@ -19,17 +17,17 @@ junit test - - ch.qos.logback - logback-classic - - com.google.protobuf - protobuf-java + com.alibaba + fastjson io.netty netty-all + + org.slf4j + slf4j-api + diff --git a/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/ChannelEventListener.java b/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/ChannelEventListener.java index 7daeeef6..ee678205 100644 --- a/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/ChannelEventListener.java +++ b/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/ChannelEventListener.java @@ -1,12 +1,28 @@ +/** + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package com.alibaba.rocketmq.remoting; import io.netty.channel.Channel; /** - * Channel¼ӶϿӽ + * 监听Channel的事件,包括连接断开、连接建立、连接异常,传送这些事件到应用层 * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * @author shijia.wxr + * @since 2013-7-13 */ public interface ChannelEventListener { public void onChannelConnect(final String remoteAddr, final Channel channel); @@ -16,4 +32,7 @@ public interface ChannelEventListener { public void onChannelException(final String remoteAddr, final Channel channel); + + + public void onChannelIdle(final String remoteAddr, final Channel channel); } diff --git a/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/CommandCustomHeader.java b/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/CommandCustomHeader.java index 20cf83a3..27b7f489 100644 --- a/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/CommandCustomHeader.java +++ b/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/CommandCustomHeader.java @@ -1,5 +1,17 @@ /** - * $Id: CommandCustomHeader.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.remoting; @@ -7,8 +19,10 @@ /** - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * RemotingCommand中自定义字段反射对象的公共接口 * + * @author shijia.wxr + * @since 2013-7-13 */ public interface CommandCustomHeader { public void checkFields() throws RemotingCommandException; diff --git a/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/InvokeCallback.java b/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/InvokeCallback.java index e2d25980..e0d67ebb 100644 --- a/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/InvokeCallback.java +++ b/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/InvokeCallback.java @@ -1,5 +1,17 @@ /** - * $Id: InvokeCallback.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.remoting; @@ -7,8 +19,10 @@ /** - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * 异步调用应答回调接口 * + * @author shijia.wxr + * @since 2013-7-13 */ public interface InvokeCallback { public void operationComplete(final ResponseFuture responseFuture); diff --git a/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/RemotingClient.java b/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/RemotingClient.java index 6ff8b6a8..e5b9a458 100644 --- a/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/RemotingClient.java +++ b/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/RemotingClient.java @@ -1,11 +1,22 @@ /** - * $Id: RemotingClient.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.remoting; import java.util.List; -import java.util.Set; -import java.util.concurrent.Executor; +import java.util.concurrent.ExecutorService; import com.alibaba.rocketmq.remoting.exception.RemotingConnectException; import com.alibaba.rocketmq.remoting.exception.RemotingSendRequestException; @@ -16,9 +27,10 @@ /** - * ԶͨţClientӿ + * 远程通信,Client接口 * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * @author shijia.wxr + * @since 2013-7-13 */ public interface RemotingClient { public void start(); @@ -27,9 +39,12 @@ public interface RemotingClient { public void updateNameServerAddressList(final List addrs); - public RemotingCommand invokeSync(final String addr, final RemotingCommand request, final long timeoutMillis) - throws InterruptedException, RemotingConnectException, RemotingSendRequestException, - RemotingTimeoutException; + public List getNameServerAddressList(); + + + public RemotingCommand invokeSync(final String addr, final RemotingCommand request, + final long timeoutMillis) throws InterruptedException, RemotingConnectException, + RemotingSendRequestException, RemotingTimeoutException; public void invokeAsync(final String addr, final RemotingCommand request, final long timeoutMillis, @@ -43,7 +58,7 @@ public void invokeOneway(final String addr, final RemotingCommand request, final public void registerProcessor(final int requestCode, final NettyRequestProcessor processor, - final Executor executor); + final ExecutorService executor); public void shutdown(); diff --git a/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/RemotingServer.java b/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/RemotingServer.java index e56fecc5..b7862602 100644 --- a/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/RemotingServer.java +++ b/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/RemotingServer.java @@ -1,11 +1,23 @@ /** - * $Id: RemotingServer.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.remoting; import io.netty.channel.Channel; -import java.util.concurrent.Executor; +import java.util.concurrent.ExecutorService; import com.alibaba.rocketmq.remoting.exception.RemotingSendRequestException; import com.alibaba.rocketmq.remoting.exception.RemotingTimeoutException; @@ -15,19 +27,27 @@ /** - * ԶͨţServerӿ + * 远程通信,Server接口 * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * @author shijia.wxr + * @since 2013-7-13 */ public interface RemotingServer { public void start() throws InterruptedException; + /** + * 注册请求处理器,ExecutorService必须要对应一个队列大小有限制的阻塞队列,防止OOM + * + * @param requestCode + * @param processor + * @param executor + */ public void registerProcessor(final int requestCode, final NettyRequestProcessor processor, - final Executor executor); + final ExecutorService executor); - public void registerDefaultProcessor(final NettyRequestProcessor processor, final Executor executor); + public void registerDefaultProcessor(final NettyRequestProcessor processor, final ExecutorService executor); public RemotingCommand invokeSync(final Channel channel, final RemotingCommand request, @@ -36,12 +56,13 @@ public RemotingCommand invokeSync(final Channel channel, final RemotingCommand r public void invokeAsync(final Channel channel, final RemotingCommand request, final long timeoutMillis, - final InvokeCallback invokeCallback) throws InterruptedException, RemotingTooMuchRequestException, - RemotingTimeoutException, RemotingSendRequestException; + final InvokeCallback invokeCallback) throws InterruptedException, + RemotingTooMuchRequestException, RemotingTimeoutException, RemotingSendRequestException; public void invokeOneway(final Channel channel, final RemotingCommand request, final long timeoutMillis) - throws InterruptedException, RemotingTooMuchRequestException, RemotingTimeoutException, RemotingSendRequestException; + throws InterruptedException, RemotingTooMuchRequestException, RemotingTimeoutException, + RemotingSendRequestException; public void shutdown(); diff --git a/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/annotation/CFNotNull.java b/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/annotation/CFNotNull.java index d28640fc..212af29e 100644 --- a/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/annotation/CFNotNull.java +++ b/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/annotation/CFNotNull.java @@ -1,22 +1,35 @@ /** - * $Id: CFNotNull.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.remoting.annotation; import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -import java.lang.annotation.ElementType; /** + * 表示字段不允许为空 * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com - * + * @author shijia.wxr + * @since 2013-7-13 */ @Documented -@Retention(RetentionPolicy.CLASS) +@Retention(RetentionPolicy.RUNTIME) @Target({ ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.LOCAL_VARIABLE }) public @interface CFNotNull { } diff --git a/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/annotation/CFNullable.java b/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/annotation/CFNullable.java index 8ba5be37..caf20990 100644 --- a/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/annotation/CFNullable.java +++ b/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/annotation/CFNullable.java @@ -1,22 +1,35 @@ /** - * $Id: CFNullable.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.remoting.annotation; import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -import java.lang.annotation.ElementType; /** + * 标识字段可以非空 * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com - * + * @author shijia.wxr + * @since 2013-7-13 */ @Documented -@Retention(RetentionPolicy.CLASS) +@Retention(RetentionPolicy.RUNTIME) @Target({ ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.LOCAL_VARIABLE }) public @interface CFNullable { } diff --git a/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/common/Pair.java b/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/common/Pair.java index aa9617c3..e3560f1a 100644 --- a/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/common/Pair.java +++ b/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/common/Pair.java @@ -1,11 +1,25 @@ /** - * $Id: Pair.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.remoting.common; /** - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * 包装2个对象 * + * @author shijia.wxr + * @since 2013-7-13 */ public class Pair { private T1 object1; diff --git a/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/common/RemotingHelper.java b/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/common/RemotingHelper.java index 2eb9508f..440b2276 100644 --- a/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/common/RemotingHelper.java +++ b/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/common/RemotingHelper.java @@ -1,5 +1,17 @@ /** - * $Id: RemotingHelper.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.remoting.common; @@ -10,203 +22,52 @@ import java.net.SocketAddress; import java.nio.ByteBuffer; import java.nio.channels.SocketChannel; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map.Entry; -import java.util.Properties; -import java.util.Set; - -import com.google.protobuf.InvalidProtocolBufferException; + import com.alibaba.rocketmq.remoting.exception.RemotingConnectException; import com.alibaba.rocketmq.remoting.exception.RemotingSendRequestException; import com.alibaba.rocketmq.remoting.exception.RemotingTimeoutException; import com.alibaba.rocketmq.remoting.protocol.RemotingCommand; -import com.alibaba.rocketmq.remoting.protocol.RemotingProtos.KVPair; -import com.alibaba.rocketmq.remoting.protocol.RemotingProtos.KVPairList; -import com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPair; -import com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPairList; -import com.alibaba.rocketmq.remoting.protocol.RemotingProtos.StringList; /** - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * 通信层一些辅助方法 * + * @author shijia.wxr + * @since 2013-7-13 */ public class RemotingHelper { public static final String RemotingLogName = "RocketmqRemoting"; - /** - * IP:PORT - */ - public static SocketAddress string2SocketAddress(final String addr) { - String[] s = addr.split(":"); - InetSocketAddress isa = new InetSocketAddress(s[0], Integer.valueOf(s[1])); - return isa; - } - - - /** - * лַб - */ - public static byte[] stringList2Bytes(final List strs) { - if (null == strs || strs.isEmpty()) { - return null; - } - - StringList.Builder builder = StringList.newBuilder(); - - for (String str : strs) { - builder.addName(str); - } - - return builder.build().toByteArray(); - } - - - /** - * лַб - */ - public static List bytes2StringList(final byte[] data) throws InvalidProtocolBufferException { - if (null == data) { - return null; - } - StringList stringList = StringList.parseFrom(data); - return stringList.getNameList(); - } - - - /** - * лֵ - */ - public static byte[] hashMap2Bytes(final HashMap nms) { - if (null == nms || nms.isEmpty()) { - return null; - } - - KVPairList.Builder builder = KVPairList.newBuilder(); - - Iterator> it = nms.entrySet().iterator(); - for (int index = 0; it.hasNext(); index++) { - Entry entry = (Entry) it.next(); - int key = entry.getKey(); - String val = entry.getValue(); - - KVPair.Builder kvb = KVPair.newBuilder(); - kvb.setKey(key); - kvb.setValue(val); - builder.addFields(index, kvb.build()); - } - - return builder.build().toByteArray(); - } - - - /** - * лֵ - * - * @throws InvalidProtocolBufferException - */ - public static HashMap bytes2HashMap(final byte[] data) - throws InvalidProtocolBufferException { - if (null == data) { - return null; - } - - HashMap result = new HashMap(); - - KVPairList kvList = KVPairList.parseFrom(data); - - List kvList2 = kvList.getFieldsList(); - - for (KVPair kv : kvList2) { - result.put(kv.getKey(), kv.getValue()); - } - - return result; - } - - - /** - * лֵ - */ - public static byte[] hashMapString2Bytes(final HashMap nms) { - if (null == nms || nms.isEmpty()) { - return null; - } - - NVPairList.Builder builder = NVPairList.newBuilder(); - - Iterator> it = nms.entrySet().iterator(); - for (int index = 0; it.hasNext(); index++) { - Entry entry = (Entry) it.next(); - String key = entry.getKey(); - String val = entry.getValue(); - - NVPair.Builder kvb = NVPair.newBuilder(); - kvb.setName(key); - kvb.setValue(val); - builder.addFields(index, kvb.build()); - } - - return builder.build().toByteArray(); - } - - - /** - * лֵ - */ - public static byte[] properties2Bytes(final Properties nms) { - if (null == nms || nms.isEmpty()) { - return null; - } - - NVPairList.Builder builder = NVPairList.newBuilder(); - - Set keyset = nms.keySet(); - int index = 0; - for (Object object : keyset) { - String key = object.toString(); - String val = nms.getProperty(key); + public static String exceptionSimpleDesc(final Throwable e) { + StringBuffer sb = new StringBuffer(); + if (e != null) { + sb.append(e.toString()); - NVPair.Builder kvb = NVPair.newBuilder(); - kvb.setName(key); - kvb.setValue(val); - builder.addFields(index++, kvb.build()); + StackTraceElement[] stackTrace = e.getStackTrace(); + if (stackTrace != null && stackTrace.length > 0) { + StackTraceElement elment = stackTrace[0]; + sb.append(", "); + sb.append(elment.toString()); + } } - return builder.build().toByteArray(); + return sb.toString(); } /** - * лֵ - * - * @throws InvalidProtocolBufferException + * IP:PORT */ - public static HashMap bytes2HashMapString(final byte[] data) - throws InvalidProtocolBufferException { - if (null == data) { - return null; - } - - HashMap result = new HashMap(); - - NVPairList ps = NVPairList.parseFrom(data); - - List ps2 = ps.getFieldsList(); - - for (NVPair kv : ps2) { - result.put(kv.getName(), kv.getValue()); - } - - return result; + public static SocketAddress string2SocketAddress(final String addr) { + String[] s = addr.split(":"); + InetSocketAddress isa = new InetSocketAddress(s[0], Integer.valueOf(s[1])); + return isa; } /** - * ӵ TODO + * 短连接调用 TODO */ public static RemotingCommand invokeSync(final String addr, final RemotingCommand request, final long timeoutMillis) throws InterruptedException, RemotingConnectException, @@ -218,7 +79,7 @@ public static RemotingCommand invokeSync(final String addr, final RemotingComman boolean sendRequestOK = false; try { - // ʹģʽ + // 使用阻塞模式 socketChannel.configureBlocking(true); /* * FIXME The read methods in SocketChannel (and DatagramChannel) @@ -227,14 +88,14 @@ public static RemotingCommand invokeSync(final String addr, final RemotingComman */ socketChannel.socket().setSoTimeout((int) timeoutMillis); - // + // 发送数据 ByteBuffer byteBufferRequest = request.encode(); while (byteBufferRequest.hasRemaining()) { int length = socketChannel.write(byteBufferRequest); if (length > 0) { if (byteBufferRequest.hasRemaining()) { if ((System.currentTimeMillis() - beginTime) > timeoutMillis) { - // ʱ + // 发送请求超时 throw new RemotingSendRequestException(addr); } } @@ -243,20 +104,20 @@ public static RemotingCommand invokeSync(final String addr, final RemotingComman throw new RemotingSendRequestException(addr); } - // Ƚ + // 比较土 Thread.sleep(1); } sendRequestOK = true; - // Ӧ SIZE + // 接收应答 SIZE ByteBuffer byteBufferSize = ByteBuffer.allocate(4); while (byteBufferSize.hasRemaining()) { int length = socketChannel.read(byteBufferSize); if (length > 0) { if (byteBufferSize.hasRemaining()) { if ((System.currentTimeMillis() - beginTime) > timeoutMillis) { - // Ӧʱ + // 接收应答超时 throw new RemotingTimeoutException(addr, timeoutMillis); } } @@ -265,11 +126,11 @@ public static RemotingCommand invokeSync(final String addr, final RemotingComman throw new RemotingTimeoutException(addr, timeoutMillis); } - // Ƚ + // 比较土 Thread.sleep(1); } - // Ӧ BODY + // 接收应答 BODY int size = byteBufferSize.getInt(0); ByteBuffer byteBufferBody = ByteBuffer.allocate(size); while (byteBufferBody.hasRemaining()) { @@ -277,7 +138,7 @@ public static RemotingCommand invokeSync(final String addr, final RemotingComman if (length > 0) { if (byteBufferBody.hasRemaining()) { if ((System.currentTimeMillis() - beginTime) > timeoutMillis) { - // Ӧʱ + // 接收应答超时 throw new RemotingTimeoutException(addr, timeoutMillis); } } @@ -286,11 +147,11 @@ public static RemotingCommand invokeSync(final String addr, final RemotingComman throw new RemotingTimeoutException(addr, timeoutMillis); } - // Ƚ + // 比较土 Thread.sleep(1); } - // Ӧݽ + // 对应答数据解码 byteBufferBody.flip(); return RemotingCommand.decode(byteBufferBody); } @@ -320,13 +181,56 @@ public static RemotingCommand invokeSync(final String addr, final RemotingComman public static String parseChannelRemoteAddr(final Channel channel) { + if (null == channel) { + return ""; + } final SocketAddress remote = channel.remoteAddress(); final String addr = remote != null ? remote.toString() : ""; if (addr.length() > 0) { - return addr.substring(1); + int index = addr.lastIndexOf("/"); + if (index >= 0) { + return addr.substring(index + 1); + } + + return addr; } return ""; } + + + public static String parseChannelRemoteName(final Channel channel) { + if (null == channel) { + return ""; + } + final InetSocketAddress remote = (InetSocketAddress) channel.remoteAddress(); + if (remote != null) { + return remote.getAddress().getHostName(); + } + return ""; + } + + + public static String parseSocketAddressAddr(SocketAddress socketAddress) { + if (socketAddress != null) { + final String addr = socketAddress.toString(); + + if (addr.length() > 0) { + return addr.substring(1); + } + } + return ""; + } + + + public static String parseSocketAddressName(SocketAddress socketAddress) { + + final InetSocketAddress addrs = (InetSocketAddress) socketAddress; + if (addrs != null) { + return addrs.getAddress().getHostName(); + } + return ""; + } + } diff --git a/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/common/RemotingUtil.java b/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/common/RemotingUtil.java index e81d84f7..bbd7f06c 100644 --- a/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/common/RemotingUtil.java +++ b/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/common/RemotingUtil.java @@ -1,8 +1,24 @@ /** - * $Id: RemotingUtil.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.remoting.common; +import io.netty.channel.Channel; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelFutureListener; + import java.io.IOException; import java.lang.reflect.Method; import java.net.Inet6Address; @@ -15,15 +31,21 @@ import java.nio.channels.Selector; import java.nio.channels.SocketChannel; import java.nio.channels.spi.SelectorProvider; +import java.util.ArrayList; import java.util.Enumeration; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** - * ط + * 网络相关方法 * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * @author shijia.wxr + * @since 2013-7-13 */ public class RemotingUtil { + private static final Logger log = LoggerFactory.getLogger(RemotingHelper.RemotingLogName); public static final String OS_NAME = System.getProperty("os.name"); private static boolean isLinuxPlatform = false; @@ -42,7 +64,7 @@ public static boolean isLinuxPlatform() { public static Selector openSelector() throws IOException { Selector result = null; - // linuxƽ̨epollʵ + // 在linux平台,尽量启用epoll实现 if (isLinuxPlatform()) { try { final Class providerClazz = Class.forName("sun.nio.ch.EPollSelectorProvider"); @@ -76,9 +98,10 @@ public static Selector openSelector() throws IOException { public static String getLocalAddress() { try { - // һǻ·ipַ + // 遍历网卡,查找一个非回路ip地址并返回 Enumeration enumeration = NetworkInterface.getNetworkInterfaces(); - InetAddress ipv6Address = null; + ArrayList ipv4Result = new ArrayList(); + ArrayList ipv6Result = new ArrayList(); while (enumeration.hasMoreElements()) { final NetworkInterface networkInterface = enumeration.nextElement(); final Enumeration en = networkInterface.getInetAddresses(); @@ -86,19 +109,33 @@ public static String getLocalAddress() { final InetAddress address = en.nextElement(); if (!address.isLoopbackAddress()) { if (address instanceof Inet6Address) { - ipv6Address = address; + ipv6Result.add(normalizeHostAddress(address)); } else { - // ʹipv4 - return normalizeHostAddress(address); + ipv4Result.add(normalizeHostAddress(address)); } } } } - // ûipv4ʹipv6 - if (ipv6Address != null) { - return normalizeHostAddress(ipv6Address); + + // 优先使用ipv4 + if (!ipv4Result.isEmpty()) { + for (String ip : ipv4Result) { + if (ip.startsWith("127.0") || ip.startsWith("192.168")) { + continue; + } + + return ip; + } + + // 取最后一个 + return ipv4Result.get(ipv4Result.size() - 1); + } + // 然后使用ipv6 + else if (!ipv6Result.isEmpty()) { + return ipv6Result.get(0); } + // 然后使用本地ip final InetAddress localHost = InetAddress.getLocalHost(); return normalizeHostAddress(localHost); } @@ -174,4 +211,16 @@ public static SocketChannel connect(SocketAddress remote, final int timeoutMilli return null; } + + + public static void closeChannel(Channel channel) { + final String addrRemote = RemotingHelper.parseChannelRemoteAddr(channel); + channel.close().addListener(new ChannelFutureListener() { + @Override + public void operationComplete(ChannelFuture future) throws Exception { + log.info("closeChannel: close the connection to remote address[{}] result: {}", addrRemote, + future.isSuccess()); + } + }); + } } diff --git a/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/common/SemaphoreReleaseOnlyOnce.java b/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/common/SemaphoreReleaseOnlyOnce.java index 6c000742..72230c97 100644 --- a/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/common/SemaphoreReleaseOnlyOnce.java +++ b/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/common/SemaphoreReleaseOnlyOnce.java @@ -1,5 +1,17 @@ /** - * $Id: SemaphoreReleaseOnlyOnce.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.remoting.common; @@ -8,10 +20,10 @@ /** - * ֻ֤ͷһ - * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * 使用布尔原子变量,信号量保证只释放一次 * + * @author shijia.wxr + * @since 2013-7-13 */ public class SemaphoreReleaseOnlyOnce { private final AtomicBoolean released = new AtomicBoolean(false); diff --git a/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/common/ServiceThread.java b/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/common/ServiceThread.java index 16dd415f..acc1982c 100644 --- a/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/common/ServiceThread.java +++ b/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/common/ServiceThread.java @@ -1,5 +1,17 @@ /** - * $Id: ServiceThread.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.remoting.common; @@ -8,19 +20,20 @@ /** - * ̨̻߳ + * 后台服务线程基类 * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * @author shijia.wxr + * @since 2013-7-13 */ public abstract class ServiceThread implements Runnable { private static final Logger stlog = LoggerFactory.getLogger(RemotingHelper.RemotingLogName); - // ִ߳ + // 执行线程 protected final Thread thread; - // ̻߳ʱ䣬Ĭ90S + // 线程回收时间,默认90S private static final long JoinTime = 90 * 1000; - // ǷѾNotify + // 是否已经被Notify过 protected volatile boolean hasNotified = false; - // ߳ǷѾֹͣ + // 线程是否已经停止 protected volatile boolean stoped = false; diff --git a/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/exception/RemotingCommandException.java b/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/exception/RemotingCommandException.java index d2aa6cc5..532320e2 100644 --- a/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/exception/RemotingCommandException.java +++ b/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/exception/RemotingCommandException.java @@ -1,11 +1,25 @@ /** - * $Id: RemotingCommandException.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.remoting.exception; /** - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * 命令解析自定义字段时,校验字段有效性抛出异常 * + * @author shijia.wxr + * @since 2013-7-13 */ public class RemotingCommandException extends RemotingException { private static final long serialVersionUID = -6061365915274953096L; diff --git a/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/exception/RemotingConnectException.java b/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/exception/RemotingConnectException.java index 8b50ddc5..4a2d88e1 100644 --- a/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/exception/RemotingConnectException.java +++ b/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/exception/RemotingConnectException.java @@ -1,11 +1,25 @@ /** - * $Id: RemotingConnectException.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.remoting.exception; /** - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * Client连接Server失败,抛出此异常 * + * @author shijia.wxr + * @since 2013-7-13 */ public class RemotingConnectException extends RemotingException { private static final long serialVersionUID = -5565366231695911316L; diff --git a/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/exception/RemotingException.java b/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/exception/RemotingException.java index 2254d8ec..27e278f2 100644 --- a/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/exception/RemotingException.java +++ b/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/exception/RemotingException.java @@ -1,11 +1,25 @@ /** - * $Id: RemotingException.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.remoting.exception; /** - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * 通信层异常父类 * + * @author shijia.wxr + * @since 2013-7-13 */ public class RemotingException extends Exception { private static final long serialVersionUID = -5690687334570505110L; diff --git a/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/exception/RemotingSendRequestException.java b/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/exception/RemotingSendRequestException.java index 0d6a033c..fc88c185 100644 --- a/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/exception/RemotingSendRequestException.java +++ b/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/exception/RemotingSendRequestException.java @@ -1,11 +1,25 @@ /** - * $Id: RemotingSendRequestException.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.remoting.exception; /** - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * RPC调用中,客户端发送请求失败,抛出此异常 * + * @author shijia.wxr + * @since 2013-7-13 */ public class RemotingSendRequestException extends RemotingException { private static final long serialVersionUID = 5391285827332471674L; diff --git a/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/exception/RemotingTimeoutException.java b/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/exception/RemotingTimeoutException.java index 406e1a3d..1211c2c6 100644 --- a/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/exception/RemotingTimeoutException.java +++ b/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/exception/RemotingTimeoutException.java @@ -1,11 +1,25 @@ /** - * $Id: RemotingTimeoutException.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.remoting.exception; /** - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * RPC调用超时异常 * + * @author shijia.wxr + * @since 2013-7-13 */ public class RemotingTimeoutException extends RemotingException { diff --git a/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/exception/RemotingTooMuchRequestException.java b/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/exception/RemotingTooMuchRequestException.java index 46e3d7fc..499503e5 100644 --- a/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/exception/RemotingTooMuchRequestException.java +++ b/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/exception/RemotingTooMuchRequestException.java @@ -1,11 +1,25 @@ /** - * $Id: RemotingTooMuchRequestException.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.remoting.exception; /** - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * 异步调用或者Oneway调用,堆积的请求超过信号量最大值 * + * @author shijia.wxr + * @since 2013-7-13 */ public class RemotingTooMuchRequestException extends RemotingException { private static final long serialVersionUID = 4326919581254519654L; diff --git a/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/netty/NettyClientConfig.java b/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/netty/NettyClientConfig.java index 10bd617f..b7d84258 100644 --- a/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/netty/NettyClientConfig.java +++ b/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/netty/NettyClientConfig.java @@ -1,23 +1,39 @@ /** - * $Id: NettyClientConfig.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.remoting.netty; /** - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * Netty客户端配置类 * + * @author shijia.wxr + * @since 2013-7-13 */ public class NettyClientConfig { - // Server Response/Request + // 处理Server Response/Request private int clientWorkerThreads = 4; - private int clientCallbackExecutorThreads = 4; + private int clientCallbackExecutorThreads = Runtime.getRuntime().availableProcessors(); private int clientSelectorThreads = 1; - private int clientOnewaySemaphoreValue = 64; - private int clientAsyncSemaphoreValue = 32; + private int clientOnewaySemaphoreValue = 256; + private int clientAsyncSemaphoreValue = 128; private long connectTimeoutMillis = 3000; - // channel1Ӳ ͹ر + // channel超过1分钟不被访问 就关闭 private long channelNotActiveInterval = 1000 * 60; + private int clientChannelMaxIdleTimeSeconds = 120; + public int getClientWorkerThreads() { return clientWorkerThreads; @@ -87,4 +103,14 @@ public int getClientAsyncSemaphoreValue() { public void setClientAsyncSemaphoreValue(int clientAsyncSemaphoreValue) { this.clientAsyncSemaphoreValue = clientAsyncSemaphoreValue; } + + + public int getClientChannelMaxIdleTimeSeconds() { + return clientChannelMaxIdleTimeSeconds; + } + + + public void setClientChannelMaxIdleTimeSeconds(int clientChannelMaxIdleTimeSeconds) { + this.clientChannelMaxIdleTimeSeconds = clientChannelMaxIdleTimeSeconds; + } } diff --git a/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/netty/NettyDecoder.java b/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/netty/NettyDecoder.java index abf62d2a..10832c55 100644 --- a/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/netty/NettyDecoder.java +++ b/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/netty/NettyDecoder.java @@ -1,5 +1,17 @@ /** - * $Id: NettyDecoder.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.remoting.netty; @@ -11,12 +23,15 @@ import org.slf4j.LoggerFactory; import com.alibaba.rocketmq.remoting.common.RemotingHelper; +import com.alibaba.rocketmq.remoting.common.RemotingUtil; import com.alibaba.rocketmq.remoting.protocol.RemotingCommand; /** - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * 协议解码器 * + * @author shijia.wxr + * @since 2013-7-13 */ public class NettyDecoder extends LengthFieldBasedFrameDecoder { private static final Logger log = LoggerFactory.getLogger(RemotingHelper.RemotingLogName); @@ -36,13 +51,18 @@ public Object decode(ChannelHandlerContext ctx, ByteBuf in) throws Exception { return null; } - return RemotingCommand.decode(frame.array()); + byte[] tmpBuf = new byte[frame.capacity()]; + frame.getBytes(0, tmpBuf); + frame.release(); + + return RemotingCommand.decode(tmpBuf); } catch (Exception e) { log.error("decode exception, " + RemotingHelper.parseChannelRemoteAddr(ctx.channel()), e); - ctx.channel().close(); + // 这里关闭后, 会在pipeline中产生事件,通过具体的close事件来清理数据结构 + RemotingUtil.closeChannel(ctx.channel()); } return null; } -} \ No newline at end of file +} diff --git a/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/netty/NettyEncoder.java b/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/netty/NettyEncoder.java index 44d0ea96..357437e3 100644 --- a/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/netty/NettyEncoder.java +++ b/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/netty/NettyEncoder.java @@ -1,5 +1,17 @@ /** - * $Id: NettyEncoder.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.remoting.netty; @@ -13,38 +25,38 @@ import org.slf4j.LoggerFactory; import com.alibaba.rocketmq.remoting.common.RemotingHelper; +import com.alibaba.rocketmq.remoting.common.RemotingUtil; import com.alibaba.rocketmq.remoting.protocol.RemotingCommand; /** - * @author vintage.wang@gmail.com shijia.wxr@taobao.com - * + * 协议编码器 + * + * @author shijia.wxr + * @since 2013-7-13 */ -public class NettyEncoder extends MessageToByteEncoder { +public class NettyEncoder extends MessageToByteEncoder { private static final Logger log = LoggerFactory.getLogger(RemotingHelper.RemotingLogName); @Override - public void encode(ChannelHandlerContext ctx, Object msg, ByteBuf out) throws Exception { - RemotingCommand cmd = null; + public void encode(ChannelHandlerContext ctx, RemotingCommand remotingCommand, ByteBuf out) + throws Exception { try { - if (msg instanceof RemotingCommand) { - cmd = (RemotingCommand) msg; - ByteBuffer header = cmd.encodeHeader(); - out.writeBytes(header); - byte[] body = cmd.getBody(); - if (body != null) { - out.writeBytes(body); - } + ByteBuffer header = remotingCommand.encodeHeader(); + out.writeBytes(header); + byte[] body = remotingCommand.getBody(); + if (body != null) { + out.writeBytes(body); } } catch (Exception e) { log.error("encode exception, " + RemotingHelper.parseChannelRemoteAddr(ctx.channel()), e); - if (cmd != null) { - log.error(cmd.toString()); + if (remotingCommand != null) { + log.error(remotingCommand.toString()); } - - ctx.channel().close(); + // 这里关闭后, 会在pipeline中产生事件,通过具体的close事件来清理数据结构 + RemotingUtil.closeChannel(ctx.channel()); } } } diff --git a/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/netty/NettyEvent.java b/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/netty/NettyEvent.java index de488278..35fc7d79 100644 --- a/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/netty/NettyEvent.java +++ b/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/netty/NettyEvent.java @@ -1,5 +1,17 @@ /** - * $Id$ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.remoting.netty; @@ -7,7 +19,10 @@ /** - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * Netty产生的各种事件 + * + * @author shijia.wxr + * @since 2013-7-13 */ public class NettyEvent { private final NettyEventType type; diff --git a/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/netty/NettyEventType.java b/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/netty/NettyEventType.java index 1ba7219c..24cb80e8 100644 --- a/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/netty/NettyEventType.java +++ b/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/netty/NettyEventType.java @@ -1,13 +1,29 @@ /** - * + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.remoting.netty; /** - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * Netty产生的事件类型 + * + * @author shijia.wxr + * @since 2013-7-13 */ public enum NettyEventType { CONNECT, CLOSE, + IDLE, EXCEPTION } diff --git a/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/netty/NettyRemotingAbstract.java b/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/netty/NettyRemotingAbstract.java index 3dd962e7..4e1bca70 100644 --- a/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/netty/NettyRemotingAbstract.java +++ b/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/netty/NettyRemotingAbstract.java @@ -1,5 +1,17 @@ /** - * $Id: NettyRemotingAbstract.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.remoting.netty; @@ -9,10 +21,10 @@ import io.netty.channel.ChannelHandlerContext; import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; +import java.util.Iterator; +import java.util.Map.Entry; import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.Executor; +import java.util.concurrent.ExecutorService; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.RejectedExecutionException; import java.util.concurrent.Semaphore; @@ -35,28 +47,30 @@ /** - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * Server与Client公用抽象类 * + * @author shijia.wxr + * @since 2013-7-13 */ public abstract class NettyRemotingAbstract { private static final Logger plog = LoggerFactory.getLogger(RemotingHelper.RemotingLogName); - // źOnewayʹãֹNetty + // 信号量,Oneway情况会使用,防止本地Netty缓存请求过多 protected final Semaphore semaphoreOneway; - // ź첽ʹãֹNetty + // 信号量,异步调用情况会使用,防止本地Netty缓存请求过多 protected final Semaphore semaphoreAsync; - // ж + // 缓存所有对外请求 protected final ConcurrentHashMap responseTable = new ConcurrentHashMap(256); - // Ĭ봦 - protected Pair defaultRequestProcessor; + // 默认请求代码处理器 + protected Pair defaultRequestProcessor; - // עĸRPC - protected final HashMap> processorTable = - new HashMap>(64); + // 注册的各个RPC处理器 + protected final HashMap> processorTable = + new HashMap>(64); protected final NettyEventExecuter nettyEventExecuter = new NettyEventExecuter(); @@ -95,6 +109,9 @@ public void run() { NettyEvent event = this.eventQueue.poll(3000, TimeUnit.MILLISECONDS); if (event != null) { switch (event.getType()) { + case IDLE: + listener.onChannelIdle(event.getRemoteAddr(), event.getChannel()); + break; case CLOSE: listener.onChannelClose(event.getRemoteAddr(), event.getChannel()); break; @@ -133,8 +150,8 @@ public NettyRemotingAbstract(final int permitsOneway, final int permitsAsync) { public void processRequestCommand(final ChannelHandlerContext ctx, final RemotingCommand cmd) { - final Pair matched = this.processorTable.get(cmd.getCode()); - final Pair pair = + final Pair matched = this.processorTable.get(cmd.getCode()); + final Pair pair = null == matched ? this.defaultRequestProcessor : matched; if (pair != null) { @@ -143,19 +160,13 @@ public void processRequestCommand(final ChannelHandlerContext ctx, final Remotin public void run() { try { final RemotingCommand response = pair.getObject1().processRequest(ctx, cmd); - if (cmd.isOnewayRPC()) { - if (response.getCode() != ResponseCode.SUCCESS_VALUE) { - plog.error("client oneway request has failed response, " - + RemotingHelper.parseChannelRemoteAddr(ctx.channel())); - plog.error(response.toString()); - } - } - else { + // Oneway形式忽略应答结果 + if (!cmd.isOnewayRPC()) { if (response != null) { response.setOpaque(cmd.getOpaque()); response.markResponseType(); try { - ctx.write(response).addListener(new ChannelFutureListener() { + ctx.writeAndFlush(response).addListener(new ChannelFutureListener() { @Override public void operationComplete(ChannelFuture future) throws Exception { if (!future.isSuccess()) { @@ -176,8 +187,7 @@ public void operationComplete(ChannelFuture future) throws Exception { } } else { - // TODO - // յ󣬵ûзӦ𣬿processRequestнӦ𣬺 + // 收到请求,但是没有返回应答,可能是processRequest中进行了应答,忽略这种情况 } } } @@ -187,51 +197,40 @@ public void operationComplete(ChannelFuture future) throws Exception { if (!cmd.isOnewayRPC()) { final RemotingCommand response = - RemotingCommand.createResponseCommand(ResponseCode.SYSTEM_ERROR_VALUE, - e.getMessage()); + RemotingCommand.createResponseCommand(ResponseCode.SYSTEM_ERROR_VALUE,// + RemotingHelper.exceptionSimpleDesc(e)); response.setOpaque(cmd.getOpaque()); - ctx.write(response); + ctx.writeAndFlush(response); } } } }; - boolean executed = false; - for (int retry = 0; retry < 3 && !executed; retry++) { - try { - pair.getObject2().execute(run); - executed = true; - break; - } - catch (RejectedExecutionException e) { - plog.warn(RemotingHelper.parseChannelRemoteAddr(ctx.channel()) - + ", system thread pool busy, RejectedExecutionException " - + pair.getObject2().toString()); - try { - Thread.sleep(2); - } - catch (InterruptedException e1) { - plog.error("", e1); - } - } + try { + // 这里需要做流控,要求线程池对应的队列必须是有大小限制的 + pair.getObject2().submit(run); } - - if (!executed) { + catch (RejectedExecutionException e) { + plog.warn(RemotingHelper.parseChannelRemoteAddr(ctx.channel()) // + + ", too many requests and system thread pool busy, RejectedExecutionException " // + + pair.getObject2().toString() // + + " request code: " + cmd.getCode()); if (!cmd.isOnewayRPC()) { final RemotingCommand response = RemotingCommand.createResponseCommand(ResponseCode.SYSTEM_BUSY_VALUE, - "system busy now, please try another node"); + "too many requests and system thread pool busy, please try another server"); response.setOpaque(cmd.getOpaque()); - ctx.write(response); + ctx.writeAndFlush(response); } } } else { String error = " request type " + cmd.getCode() + " not supported"; final RemotingCommand response = - RemotingCommand.createResponseCommand(ResponseCode.REQUEST_CODE_NOT_SUPPORTED_VALUE, error); + RemotingCommand.createResponseCommand(ResponseCode.REQUEST_CODE_NOT_SUPPORTED_VALUE, + error); response.setOpaque(cmd.getOpaque()); - ctx.write(response); + ctx.writeAndFlush(response); plog.error(RemotingHelper.parseChannelRemoteAddr(ctx.channel()) + error); } } @@ -244,17 +243,17 @@ public void processResponseCommand(ChannelHandlerContext ctx, RemotingCommand cm responseFuture.release(); - // 첽 + // 异步调用 if (responseFuture.getInvokeCallback() != null) { boolean runInThisThread = false; - Executor executor = this.getCallbackExecutor(); + ExecutorService executor = this.getCallbackExecutor(); if (executor != null) { try { - executor.execute(new Runnable() { + executor.submit(new Runnable() { @Override public void run() { try { - responseFuture.getInvokeCallback().operationComplete(responseFuture); + responseFuture.executeInvokeCallback(); } catch (Throwable e) { plog.warn("excute callback in executor exception, and callback throw", e); @@ -273,14 +272,14 @@ public void run() { if (runInThisThread) { try { - responseFuture.getInvokeCallback().operationComplete(responseFuture); + responseFuture.executeInvokeCallback(); } catch (Throwable e) { plog.warn("", e); } } } - // ͬ + // 同步调用 else { responseFuture.putResponse(cmd); } @@ -295,8 +294,8 @@ public void run() { } - public void processMessageReceived(ChannelHandlerContext ctx, Object msg) throws Exception { - final RemotingCommand cmd = (RemotingCommand) msg; + public void processMessageReceived(ChannelHandlerContext ctx, RemotingCommand msg) throws Exception { + final RemotingCommand cmd = msg; if (cmd != null) { switch (cmd.getType()) { case REQUEST_COMMAND: @@ -312,31 +311,26 @@ public void processMessageReceived(ChannelHandlerContext ctx, Object msg) throws } - abstract public Executor getCallbackExecutor(); + abstract public ExecutorService getCallbackExecutor(); public void scanResponseTable() { - List todoList = new LinkedList(); + Iterator> it = this.responseTable.entrySet().iterator(); + while (it.hasNext()) { + Entry next = it.next(); + ResponseFuture rep = next.getValue(); - for (ResponseFuture rep : this.responseTable.values()) { if ((rep.getBeginTimestamp() + rep.getTimeoutMillis() + 1000) <= System.currentTimeMillis()) { - todoList.add(rep.getOpaque()); - if (rep.getInvokeCallback() != null) { - try { - rep.getInvokeCallback().operationComplete(rep); - } - catch (Throwable e) { - plog.error("scanResponseTable, operationComplete exception", e); - } + it.remove(); + rep.release(); + try { + rep.executeInvokeCallback(); + } + catch (Throwable e) { + plog.error("scanResponseTable, operationComplete exception", e); } - } - } - for (Integer opaque : todoList) { - ResponseFuture responseFuture = this.responseTable.remove(opaque); - if (responseFuture != null) { - responseFuture.release(); - plog.warn("remove timeout request, " + responseFuture); + plog.warn("remove timeout request, " + rep); } } } @@ -349,7 +343,7 @@ public RemotingCommand invokeSyncImpl(final Channel channel, final RemotingComma final ResponseFuture responseFuture = new ResponseFuture(request.getOpaque(), timeoutMillis, null, null); this.responseTable.put(request.getOpaque(), responseFuture); - channel.write(request).addListener(new ChannelFutureListener() { + channel.writeAndFlush(request).addListener(new ChannelFutureListener() { @Override public void operationComplete(ChannelFuture f) throws Exception { if (f.isSuccess()) { @@ -370,12 +364,12 @@ public void operationComplete(ChannelFuture f) throws Exception { RemotingCommand responseCommand = responseFuture.waitResponse(timeoutMillis); if (null == responseCommand) { - // ɹȡӦʱ + // 发送请求成功,读取应答超时 if (responseFuture.isSendRequestOK()) { throw new RemotingTimeoutException(RemotingHelper.parseChannelRemoteAddr(channel), timeoutMillis, responseFuture.getCause()); } - // ʧ + // 发送请求失败 else { throw new RemotingSendRequestException(RemotingHelper.parseChannelRemoteAddr(channel), responseFuture.getCause()); @@ -390,9 +384,9 @@ public void operationComplete(ChannelFuture f) throws Exception { } - public void invokeAsyncImpl(final Channel channel, final RemotingCommand request, final long timeoutMillis, - final InvokeCallback invokeCallback) throws InterruptedException, RemotingTooMuchRequestException, - RemotingTimeoutException, RemotingSendRequestException { + public void invokeAsyncImpl(final Channel channel, final RemotingCommand request, + final long timeoutMillis, final InvokeCallback invokeCallback) throws InterruptedException, + RemotingTooMuchRequestException, RemotingTimeoutException, RemotingSendRequestException { boolean acquired = this.semaphoreAsync.tryAcquire(timeoutMillis, TimeUnit.MILLISECONDS); if (acquired) { final SemaphoreReleaseOnlyOnce once = new SemaphoreReleaseOnlyOnce(this.semaphoreAsync); @@ -401,7 +395,7 @@ public void invokeAsyncImpl(final Channel channel, final RemotingCommand request new ResponseFuture(request.getOpaque(), timeoutMillis, invokeCallback, once); this.responseTable.put(request.getOpaque(), responseFuture); try { - channel.write(request).addListener(new ChannelFutureListener() { + channel.writeAndFlush(request).addListener(new ChannelFutureListener() { @Override public void operationComplete(ChannelFuture f) throws Exception { if (f.isSuccess()) { @@ -412,12 +406,14 @@ public void operationComplete(ChannelFuture f) throws Exception { responseFuture.setSendRequestOK(false); } - once.release(); + responseFuture.putResponse(null); + responseFuture.executeInvokeCallback(); responseTable.remove(request.getOpaque()); - responseFuture.putResponse(null); - plog.warn("send a request command to channel <" + channel.remoteAddress() + "> failed."); + plog.warn("send a request command to channel <" + channel.remoteAddress() + + "> failed."); plog.warn(request.toString()); + } }); } @@ -442,15 +438,15 @@ public void operationComplete(ChannelFuture f) throws Exception { } - public void invokeOnewayImpl(final Channel channel, final RemotingCommand request, final long timeoutMillis) - throws InterruptedException, RemotingTooMuchRequestException, RemotingTimeoutException, - RemotingSendRequestException { + public void invokeOnewayImpl(final Channel channel, final RemotingCommand request, + final long timeoutMillis) throws InterruptedException, RemotingTooMuchRequestException, + RemotingTimeoutException, RemotingSendRequestException { request.markOnewayRPC(); boolean acquired = this.semaphoreOneway.tryAcquire(timeoutMillis, TimeUnit.MILLISECONDS); if (acquired) { final SemaphoreReleaseOnlyOnce once = new SemaphoreReleaseOnlyOnce(this.semaphoreOneway); try { - channel.write(request).addListener(new ChannelFutureListener() { + channel.writeAndFlush(request).addListener(new ChannelFutureListener() { @Override public void operationComplete(ChannelFuture f) throws Exception { once.release(); diff --git a/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/netty/NettyRemotingClient.java b/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/netty/NettyRemotingClient.java index 5621f771..49cffcca 100644 --- a/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/netty/NettyRemotingClient.java +++ b/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/netty/NettyRemotingClient.java @@ -1,5 +1,17 @@ /** - * $Id: NettyRemotingClient.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.remoting.netty; @@ -7,24 +19,27 @@ import io.netty.channel.Channel; import io.netty.channel.ChannelDuplexHandler; import io.netty.channel.ChannelFuture; -import io.netty.channel.ChannelFutureListener; import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.ChannelInboundMessageHandlerAdapter; import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelOption; import io.netty.channel.ChannelPromise; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.SimpleChannelInboundHandler; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.SocketChannel; import io.netty.channel.socket.nio.NioSocketChannel; +import io.netty.handler.timeout.IdleState; +import io.netty.handler.timeout.IdleStateEvent; +import io.netty.handler.timeout.IdleStateHandler; import io.netty.util.concurrent.DefaultEventExecutorGroup; import java.net.SocketAddress; +import java.util.Collections; import java.util.List; import java.util.Random; import java.util.Timer; import java.util.TimerTask; import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.Executor; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.ThreadFactory; @@ -42,6 +57,7 @@ import com.alibaba.rocketmq.remoting.RemotingClient; import com.alibaba.rocketmq.remoting.common.Pair; import com.alibaba.rocketmq.remoting.common.RemotingHelper; +import com.alibaba.rocketmq.remoting.common.RemotingUtil; import com.alibaba.rocketmq.remoting.exception.RemotingConnectException; import com.alibaba.rocketmq.remoting.exception.RemotingSendRequestException; import com.alibaba.rocketmq.remoting.exception.RemotingTimeoutException; @@ -50,8 +66,10 @@ /** - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * Remoting客户端实现 * + * @author shijia.wxr + * @since 2013-7-13 */ public class NettyRemotingClient extends NettyRemotingAbstract implements RemotingClient { private static final Logger log = LoggerFactory.getLogger(RemotingHelper.RemotingLogName); @@ -60,62 +78,70 @@ public class NettyRemotingClient extends NettyRemotingAbstract implements Remoti private final NettyClientConfig nettyClientConfig; private final Bootstrap bootstrap = new Bootstrap(); + private final EventLoopGroup eventLoopGroup; + private DefaultEventExecutorGroup defaultEventExecutorGroup; private final Lock lockChannelTables = new ReentrantLock(); private final ConcurrentHashMap channelTables = new ConcurrentHashMap(); - // ʱ + // 定时器 private final Timer timer = new Timer("ClientHouseKeepingService", true); - // Name server + // Name server相关 private final AtomicReference> namesrvAddrList = new AtomicReference>(); private final AtomicReference namesrvAddrChoosed = new AtomicReference(); private final AtomicInteger namesrvIndex = new AtomicInteger(initValueIndex()); private final Lock lockNamesrvChannel = new ReentrantLock(); - // CallbackӦ + // 处理Callback应答器 private final ExecutorService publicExecutor; private final ChannelEventListener channelEventListener; class ChannelWrapper { - private final Channel channel; - private volatile long lastActiveTimestamp = System.currentTimeMillis(); + private final ChannelFuture channelFuture; - public ChannelWrapper(Channel channel) { - this.channel = channel; + public ChannelWrapper(ChannelFuture channelFuture) { + this.channelFuture = channelFuture; } - public long getLastActiveTimestamp() { - return lastActiveTimestamp; + public boolean isOK() { + return (this.channelFuture.channel() != null && this.channelFuture.channel().isActive()); } - public void setLastActiveTimestamp(long lastActiveTimestamp) { - this.lastActiveTimestamp = lastActiveTimestamp; + private Channel getChannel() { + return this.channelFuture.channel(); } - public Channel getChannel() { - return channel; + public ChannelFuture getChannelFuture() { + return channelFuture; } } - class NettyClientHandler extends ChannelInboundMessageHandlerAdapter { + class NettyClientHandler extends SimpleChannelInboundHandler { + + // @Override + // protected void messageReceived(ChannelHandlerContext ctx, + // RemotingCommand msg) throws Exception { + // processMessageReceived(ctx, msg); + // } @Override - public void messageReceived(ChannelHandlerContext ctx, Object msg) throws Exception { + protected void channelRead0(ChannelHandlerContext ctx, RemotingCommand msg) throws Exception { processMessageReceived(ctx, msg); + } } class NettyConnetManageHandler extends ChannelDuplexHandler { @Override - public void connect(ChannelHandlerContext ctx, SocketAddress remoteAddress, SocketAddress localAddress, - ChannelPromise promise) throws Exception { + public void connect(ChannelHandlerContext ctx, SocketAddress remoteAddress, + SocketAddress localAddress, ChannelPromise promise) throws Exception { final String local = localAddress == null ? "UNKNOW" : localAddress.toString(); final String remote = remoteAddress == null ? "UNKNOW" : remoteAddress.toString(); log.info("NETTY CLIENT PIPELINE: CONNECT {} => {}", local, remote); @@ -156,18 +182,6 @@ public void close(ChannelHandlerContext ctx, ChannelPromise promise) throws Exce } - @Override - public void flush(ChannelHandlerContext ctx, ChannelPromise promise) throws Exception { - ctx.flush(promise); - } - - - @Override - public void inboundBufferUpdated(ChannelHandlerContext ctx) throws Exception { - ctx.fireInboundBufferUpdated(); - } - - @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { final String remoteAddress = RemotingHelper.parseChannelRemoteAddr(ctx.channel()); @@ -179,13 +193,32 @@ public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws E .toString(), ctx.channel())); } } + + + @Override + public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception { + if (evt instanceof IdleStateEvent) { + IdleStateEvent evnet = (IdleStateEvent) evt; + if (evnet.state().equals(IdleState.ALL_IDLE)) { + final String remoteAddress = RemotingHelper.parseChannelRemoteAddr(ctx.channel()); + log.warn("NETTY CLIENT PIPELINE: IDLE exception [{}]", remoteAddress); + closeChannel(ctx.channel()); + if (NettyRemotingClient.this.channelEventListener != null) { + NettyRemotingClient.this.putNettyEvent(new NettyEvent(NettyEventType.IDLE, + remoteAddress.toString(), ctx.channel())); + } + } + } + + ctx.fireUserEventTriggered(evt); + } } private static int initValueIndex() { Random r = new Random(); - return Math.abs(r.nextInt()) % 999; + return Math.abs(r.nextInt() % 999) % 999; } @@ -196,7 +229,8 @@ public NettyRemotingClient(final NettyClientConfig nettyClientConfig) { public NettyRemotingClient(final NettyClientConfig nettyClientConfig, final ChannelEventListener channelEventListener) { - super(nettyClientConfig.getClientOnewaySemaphoreValue(), nettyClientConfig.getClientAsyncSemaphoreValue()); + super(nettyClientConfig.getClientOnewaySemaphoreValue(), nettyClientConfig + .getClientAsyncSemaphoreValue()); this.nettyClientConfig = nettyClientConfig; this.channelEventListener = channelEventListener; @@ -215,53 +249,40 @@ public Thread newThread(Runnable r) { } }); - } - - - private void scanNotActiveChannel() throws InterruptedException { - // ɨ - if (this.lockChannelTables.tryLock(LockTimeoutMillis, TimeUnit.MILLISECONDS)) { - try { - for (String addr : this.channelTables.keySet()) { - ChannelWrapper cw = this.channelTables.get(addr); - if (cw != null) { - long diff = System.currentTimeMillis() - cw.getLastActiveTimestamp(); - if (diff > this.nettyClientConfig.getChannelNotActiveInterval()) { - log.warn("the channel[{}] not active for a while[{}ms], close it forcibly", addr, diff); - this.closeChannel(addr, cw.getChannel()); - } - } - } - } - catch (Exception e) { - log.error("scanNotActiveChannel: close channel exception", e); - } - finally { - this.lockChannelTables.unlock(); - } - } - else { - log.warn("scanNotActiveChannel: try to lock channel table, but timeout, {}ms", LockTimeoutMillis); - } + this.eventLoopGroup = new NioEventLoopGroup(nettyClientConfig.getClientSelectorThreads()); } @Override public void start() { - this.bootstrap.group(new NioEventLoopGroup(nettyClientConfig.getClientSelectorThreads())) - .channel(NioSocketChannel.class).option(ChannelOption.TCP_NODELAY, true) - .handler(new ChannelInitializer() { + this.defaultEventExecutorGroup = new DefaultEventExecutorGroup(// + nettyClientConfig.getClientWorkerThreads(), // + new ThreadFactory() { + + private AtomicInteger threadIndex = new AtomicInteger(0); + + + @Override + public Thread newThread(Runnable r) { + return new Thread(r, "NettyClientWorkerThread_" + this.threadIndex.incrementAndGet()); + } + }); + + this.bootstrap.group(this.eventLoopGroup).channel(NioSocketChannel.class) + .option(ChannelOption.TCP_NODELAY, true).handler(new ChannelInitializer() { @Override public void initChannel(SocketChannel ch) throws Exception { ch.pipeline().addLast(// - new DefaultEventExecutorGroup(nettyClientConfig.getClientWorkerThreads()), // + defaultEventExecutorGroup, // new NettyEncoder(), // new NettyDecoder(), // - new NettyConnetManageHandler(), new NettyClientHandler()); + new IdleStateHandler(0, 0, nettyClientConfig.getClientChannelMaxIdleTimeSeconds()),// + new NettyConnetManageHandler(), // + new NettyClientHandler()); } }); - // ÿ1ɨ첽óʱ + // 每隔1秒扫描下异步调用超时情况 this.timer.scheduleAtFixedRate(new TimerTask() { @Override @@ -275,20 +296,6 @@ public void run() { } }, 1000 * 3, 1000); - // ÿ10ɨ² - this.timer.scheduleAtFixedRate(new TimerTask() { - - @Override - public void run() { - try { - NettyRemotingClient.this.scanNotActiveChannel(); - } - catch (Exception e) { - log.error("scanNotActiveChannel exception", e); - } - } - }, 1000 * 10, 1000 * 10); - if (this.channelEventListener != null) { this.nettyEventExecuter.start(); } @@ -298,10 +305,6 @@ public void run() { @Override public void shutdown() { try { - if (this.nettyEventExecuter != null) { - this.nettyEventExecuter.shutdown(); - } - this.timer.cancel(); for (ChannelWrapper cw : this.channelTables.values()) { @@ -310,7 +313,15 @@ public void shutdown() { this.channelTables.clear(); - this.bootstrap.shutdown(); + this.eventLoopGroup.shutdownGracefully(); + + if (this.nettyEventExecuter != null) { + this.nettyEventExecuter.shutdown(); + } + + if (this.defaultEventExecutorGroup != null) { + this.defaultEventExecutorGroup.shutdownGracefully(); + } } catch (Exception e) { log.error("NettyRemotingClient shutdown exception, ", e); @@ -332,8 +343,7 @@ private Channel getAndCreateChannel(final String addr) throws InterruptedExcepti return getAndCreateNameserverChannel(); ChannelWrapper cw = this.channelTables.get(addr); - if (cw != null) { - cw.setLastActiveTimestamp(System.currentTimeMillis()); + if (cw != null && cw.isOK()) { return cw.getChannel(); } @@ -345,21 +355,19 @@ private Channel getAndCreateNameserverChannel() throws InterruptedException { String addr = this.namesrvAddrChoosed.get(); if (addr != null) { ChannelWrapper cw = this.channelTables.get(addr); - if (cw != null) { - cw.setLastActiveTimestamp(System.currentTimeMillis()); + if (cw != null && cw.isOK()) { return cw.getChannel(); } } final List addrList = this.namesrvAddrList.get(); - // Դ + // 加锁,尝试创建连接 if (this.lockNamesrvChannel.tryLock(LockTimeoutMillis, TimeUnit.MILLISECONDS)) { try { addr = this.namesrvAddrChoosed.get(); if (addr != null) { ChannelWrapper cw = this.channelTables.get(addr); - if (cw != null) { - cw.setLastActiveTimestamp(System.currentTimeMillis()); + if (cw != null && cw.isOK()) { return cw.getChannel(); } } @@ -395,33 +403,43 @@ private Channel getAndCreateNameserverChannel() throws InterruptedException { private Channel createChannel(final String addr) throws InterruptedException { - // Դ + ChannelWrapper cw = this.channelTables.get(addr); + if (cw != null && cw.isOK()) { + return cw.getChannel(); + } + + // 进入临界区后,不能有阻塞操作,网络连接采用异步方式 if (this.lockChannelTables.tryLock(LockTimeoutMillis, TimeUnit.MILLISECONDS)) { try { - ChannelWrapper cw = this.channelTables.get(addr); + boolean createNewConnection = false; + cw = this.channelTables.get(addr); if (cw != null) { - cw.setLastActiveTimestamp(System.currentTimeMillis()); - return cw.getChannel(); - } - - ChannelFuture channelFuture = this.bootstrap.connect(RemotingHelper.string2SocketAddress(addr)); - Channel channel = null; - if (channelFuture.awaitUninterruptibly(this.nettyClientConfig.getConnectTimeoutMillis())) { - channel = channelFuture.channel(); - if (!channel.isActive()) { - log.warn("connect {} in {}ms ok, but channel not active", addr, - this.nettyClientConfig.getConnectTimeoutMillis()); - return null; + // channel正常 + if (cw.isOK()) { + return cw.getChannel(); + } + // 正在连接,退出锁等待 + else if (!cw.getChannelFuture().isDone()) { + createNewConnection = false; + } + // 说明连接不成功 + else { + this.channelTables.remove(addr); + createNewConnection = true; } } + // ChannelWrapper不存在 else { - log.error("connect {} in {}ms timeout", addr, this.nettyClientConfig.getConnectTimeoutMillis()); - return null; + createNewConnection = true; } - log.info("connect {} success, and add to the channel table", addr); - this.channelTables.put(addr, new ChannelWrapper(channel)); - return channel; + if (createNewConnection) { + ChannelFuture channelFuture = + this.bootstrap.connect(RemotingHelper.string2SocketAddress(addr)); + log.info("createChannel: begin to connect remote host[{}] asynchronously", addr); + cw = new ChannelWrapper(channelFuture); + this.channelTables.put(addr, cw); + } } catch (Exception e) { log.error("createChannel: create channel exception", e); @@ -434,6 +452,26 @@ private Channel createChannel(final String addr) throws InterruptedException { log.warn("createChannel: try to lock channel table, but timeout, {}ms", LockTimeoutMillis); } + if (cw != null) { + ChannelFuture channelFuture = cw.getChannelFuture(); + if (channelFuture.awaitUninterruptibly(this.nettyClientConfig.getConnectTimeoutMillis())) { + if (cw.isOK()) { + log.info("createChannel: connect remote host[{}] success, {}", addr, + channelFuture.toString()); + return cw.getChannel(); + } + else { + log.warn( + "createChannel: connect remote host[" + addr + "] failed, " + + channelFuture.toString(), channelFuture.cause()); + } + } + else { + log.warn("createChannel: connect remote host[{}] timeout {}ms, {}", addr, + this.nettyClientConfig.getConnectTimeoutMillis(), channelFuture.toString()); + } + } + return null; } @@ -450,10 +488,12 @@ public void closeChannel(final String addr, final Channel channel) { boolean removeItemFromTable = true; final ChannelWrapper prevCW = this.channelTables.get(addrRemote); - log.info("closeChannel: begin close the channel[{}] Found: {}", addrRemote, (prevCW != null)); + log.info("closeChannel: begin close the channel[{}] Found: {}", addrRemote, + (prevCW != null)); if (null == prevCW) { - log.info("closeChannel: the channel[{}] has been removed from the channel table before", + log.info( + "closeChannel: the channel[{}] has been removed from the channel table before", addrRemote); removeItemFromTable = false; } @@ -469,13 +509,7 @@ else if (prevCW.getChannel() != channel) { log.info("closeChannel: the channel[{}] was removed from channel table", addrRemote); } - channel.close().addListener(new ChannelFutureListener() { - @Override - public void operationComplete(ChannelFuture future) throws Exception { - log.info("closeChannel: close the connection to remote address[{}] result: {}", - addrRemote, future.isSuccess()); - } - }); + RemotingUtil.closeChannel(channel); } catch (Exception e) { log.error("closeChannel: close the channel exception", e); @@ -506,22 +540,26 @@ public void closeChannel(final Channel channel) { String addrRemote = null; for (String key : channelTables.keySet()) { ChannelWrapper prev = this.channelTables.get(key); - if (prev.channel.equals(channel)) { - prevCW = prev; - addrRemote = key; - break; + if (prev.getChannel() != null) { + if (prev.getChannel() == channel) { + prevCW = prev; + addrRemote = key; + break; + } } } if (null == prevCW) { - log.info("eventCloseChannel: the channel[[" + addrRemote - + "]] has been removed from the channel table before"); + log.info( + "eventCloseChannel: the channel[{}] has been removed from the channel table before", + addrRemote); removeItemFromTable = false; } if (removeItemFromTable) { this.channelTables.remove(addrRemote); - log.info("closeChannel: the channel[" + addrRemote + "] was removed from channel table"); + log.info("closeChannel: the channel[{}] was removed from channel table", addrRemote); + RemotingUtil.closeChannel(channel); } } catch (Exception e) { @@ -542,14 +580,14 @@ public void closeChannel(final Channel channel) { @Override - public void registerProcessor(int requestCode, NettyRequestProcessor processor, Executor executor) { - Executor executorThis = executor; + public void registerProcessor(int requestCode, NettyRequestProcessor processor, ExecutorService executor) { + ExecutorService executorThis = executor; if (null == executor) { executorThis = this.publicExecutor; } - Pair pair = - new Pair(processor, executorThis); + Pair pair = + new Pair(processor, executorThis); this.processorTable.put(requestCode, pair); } @@ -569,8 +607,9 @@ public RemotingCommand invokeSync(String addr, final RemotingCommand request, lo throw e; } catch (RemotingTimeoutException e) { - log.warn("invokeSync: wait response timeout exception, so close the channel[{}]", addr); - this.closeChannel(addr, channel); + log.warn("invokeSync: wait response timeout exception, the channel[{}]", addr); + // 超时异常如果关闭连接可能会产生连锁反应 + // this.closeChannel(addr, channel); throw e; } } @@ -582,9 +621,9 @@ public RemotingCommand invokeSync(String addr, final RemotingCommand request, lo @Override - public void invokeAsync(String addr, RemotingCommand request, long timeoutMillis, InvokeCallback invokeCallback) - throws InterruptedException, RemotingConnectException, RemotingTooMuchRequestException, - RemotingTimeoutException, RemotingSendRequestException { + public void invokeAsync(String addr, RemotingCommand request, long timeoutMillis, + InvokeCallback invokeCallback) throws InterruptedException, RemotingConnectException, + RemotingTooMuchRequestException, RemotingTimeoutException, RemotingSendRequestException { final Channel channel = this.getAndCreateChannel(addr); if (channel != null && channel.isActive()) { try { @@ -626,7 +665,7 @@ public void invokeOneway(String addr, RemotingCommand request, long timeoutMilli @Override - public Executor getCallbackExecutor() { + public ExecutorService getCallbackExecutor() { return this.publicExecutor; } @@ -634,23 +673,28 @@ public Executor getCallbackExecutor() { @Override public void updateNameServerAddressList(List addrs) { List old = this.namesrvAddrList.get(); - // £Ҫ - if (!addrs.isEmpty() && old != null) { - if (old.size() == addrs.size()) { - boolean equal = true; - for (int i = 0; i < addrs.size(); i++) { - if (!old.get(i).equals(addrs.get(i))) { - equal = false; - break; + boolean update = false; + + if (!addrs.isEmpty()) { + if (null == old) { + update = true; + } + else if (addrs.size() != old.size()) { + update = true; + } + else { + for (int i = 0; i < addrs.size() && !update; i++) { + if (!old.contains(addrs.get(i))) { + update = true; } } + } - if (equal) - return; + if (update) { + Collections.shuffle(addrs); + this.namesrvAddrList.set(addrs); } } - - this.namesrvAddrList.set(addrs); } @@ -658,4 +702,15 @@ public void updateNameServerAddressList(List addrs) { public ChannelEventListener getChannelEventListener() { return channelEventListener; } + + + public List getNamesrvAddrList() { + return namesrvAddrList.get(); + } + + + @Override + public List getNameServerAddressList() { + return this.namesrvAddrList.get(); + } } diff --git a/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/netty/NettyRemotingServer.java b/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/netty/NettyRemotingServer.java index 853c5ed4..029ca115 100644 --- a/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/netty/NettyRemotingServer.java +++ b/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/netty/NettyRemotingServer.java @@ -1,5 +1,17 @@ /** - * $Id: NettyRemotingServer.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.remoting.netty; @@ -7,17 +19,21 @@ import io.netty.channel.Channel; import io.netty.channel.ChannelDuplexHandler; import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.ChannelInboundMessageHandlerAdapter; import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelOption; -import io.netty.channel.ChannelPromise; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.SimpleChannelInboundHandler; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.SocketChannel; import io.netty.channel.socket.nio.NioServerSocketChannel; +import io.netty.handler.timeout.IdleState; +import io.netty.handler.timeout.IdleStateEvent; +import io.netty.handler.timeout.IdleStateHandler; import io.netty.util.concurrent.DefaultEventExecutorGroup; import java.net.InetSocketAddress; -import java.util.concurrent.Executor; +import java.util.Timer; +import java.util.TimerTask; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.ThreadFactory; @@ -31,6 +47,7 @@ import com.alibaba.rocketmq.remoting.RemotingServer; import com.alibaba.rocketmq.remoting.common.Pair; import com.alibaba.rocketmq.remoting.common.RemotingHelper; +import com.alibaba.rocketmq.remoting.common.RemotingUtil; import com.alibaba.rocketmq.remoting.exception.RemotingSendRequestException; import com.alibaba.rocketmq.remoting.exception.RemotingTimeoutException; import com.alibaba.rocketmq.remoting.exception.RemotingTooMuchRequestException; @@ -38,97 +55,22 @@ /** - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * Remoting服务端实现 * + * @author shijia.wxr + * @since 2013-7-13 */ public class NettyRemotingServer extends NettyRemotingAbstract implements RemotingServer { private static final Logger log = LoggerFactory.getLogger(RemotingHelper.RemotingLogName); - - private ServerBootstrap serverBootstrap; - private NettyServerConfig nettyServerConfig; - - // CallbackӦ + private final ServerBootstrap serverBootstrap; + private final EventLoopGroup eventLoopGroup; + private final NettyServerConfig nettyServerConfig; + // 处理Callback应答器 private final ExecutorService publicExecutor; - private final ChannelEventListener channelEventListener; - - class NettyServerHandler extends ChannelInboundMessageHandlerAdapter { - - @Override - public void messageReceived(final ChannelHandlerContext ctx, Object msg) throws Exception { - processMessageReceived(ctx, msg); - } - } - - class NettyConnetManageHandler extends ChannelDuplexHandler { - @Override - public void channelRegistered(ChannelHandlerContext ctx) throws Exception { - final String remoteAddress = RemotingHelper.parseChannelRemoteAddr(ctx.channel()); - log.info("NETTY SERVER PIPELINE: channelRegistered {}", remoteAddress); - super.channelRegistered(ctx); - } - - - @Override - public void channelActive(ChannelHandlerContext ctx) throws Exception { - final String remoteAddress = RemotingHelper.parseChannelRemoteAddr(ctx.channel()); - log.info("NETTY SERVER PIPELINE: channelActive, the channel[{}]", remoteAddress); - super.channelActive(ctx); - - if (NettyRemotingServer.this.channelEventListener != null) { - NettyRemotingServer.this.putNettyEvent(new NettyEvent(NettyEventType.CONNECT, remoteAddress - .toString(), ctx.channel())); - } - } - - - @Override - public void channelInactive(ChannelHandlerContext ctx) throws Exception { - final String remoteAddress = RemotingHelper.parseChannelRemoteAddr(ctx.channel()); - log.info("NETTY SERVER PIPELINE: channelInactive, the channel[{}]", remoteAddress); - super.channelInactive(ctx); - - if (NettyRemotingServer.this.channelEventListener != null) { - NettyRemotingServer.this.putNettyEvent(new NettyEvent(NettyEventType.CLOSE, remoteAddress - .toString(), ctx.channel())); - } - } - - - @Override - public void channelUnregistered(ChannelHandlerContext ctx) throws Exception { - final String remoteAddress = RemotingHelper.parseChannelRemoteAddr(ctx.channel()); - log.info("NETTY SERVER PIPELINE: channelUnregistered, the channel[{}]", remoteAddress); - super.channelUnregistered(ctx); - } - - - @Override - public void flush(ChannelHandlerContext ctx, ChannelPromise promise) throws Exception { - ctx.flush(promise); - } - - - @Override - public void inboundBufferUpdated(ChannelHandlerContext ctx) throws Exception { - ctx.fireInboundBufferUpdated(); - } - - - @Override - public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { - final String remoteAddress = RemotingHelper.parseChannelRemoteAddr(ctx.channel()); - log.warn("NETTY SERVER PIPELINE: exceptionCaught {}", remoteAddress); - log.warn("NETTY SERVER PIPELINE: exceptionCaught exception.", cause); - - if (NettyRemotingServer.this.channelEventListener != null) { - NettyRemotingServer.this.putNettyEvent(new NettyEvent(NettyEventType.EXCEPTION, remoteAddress - .toString(), ctx.channel())); - } - - ctx.channel().close(); - } - } + // 定时器 + private final Timer timer = new Timer("ServerHouseKeepingService", true); + private DefaultEventExecutorGroup defaultEventExecutorGroup; public NettyRemotingServer(final NettyServerConfig nettyServerConfig) { @@ -138,7 +80,8 @@ public NettyRemotingServer(final NettyServerConfig nettyServerConfig) { public NettyRemotingServer(final NettyServerConfig nettyServerConfig, final ChannelEventListener channelEventListener) { - super(nettyServerConfig.getServerOnewaySemaphoreValue(), nettyServerConfig.getServerAsyncSemaphoreValue()); + super(nettyServerConfig.getServerOnewaySemaphoreValue(), nettyServerConfig + .getServerAsyncSemaphoreValue()); this.serverBootstrap = new ServerBootstrap(); this.nettyServerConfig = nettyServerConfig; this.channelEventListener = channelEventListener; @@ -157,24 +100,44 @@ public Thread newThread(Runnable r) { return new Thread(r, "NettyServerPublicExecutor_" + this.threadIndex.incrementAndGet()); } }); + + this.eventLoopGroup = new NioEventLoopGroup(nettyServerConfig.getServerSelectorThreads()); } @Override public void start() throws InterruptedException { - this.serverBootstrap - .group(new NioEventLoopGroup(this.nettyServerConfig.getServerSelectorThreads()), - new NioEventLoopGroup()).channel(NioServerSocketChannel.class) - .option(ChannelOption.SO_BACKLOG, 65536).childOption(ChannelOption.TCP_NODELAY, true) + this.defaultEventExecutorGroup = new DefaultEventExecutorGroup(// + nettyServerConfig.getServerWorkerThreads(), // + new ThreadFactory() { + + private AtomicInteger threadIndex = new AtomicInteger(0); + + + @Override + public Thread newThread(Runnable r) { + return new Thread(r, "NettyServerWorkerThread_" + this.threadIndex.incrementAndGet()); + } + }); + + this.serverBootstrap.group(this.eventLoopGroup, new NioEventLoopGroup()) + .channel(NioServerSocketChannel.class) + .option(ChannelOption.SO_BACKLOG, 65536) + .option(ChannelOption.SO_REUSEADDR, true) + // + .childOption(ChannelOption.TCP_NODELAY, true) .localAddress(new InetSocketAddress(this.nettyServerConfig.getListenPort())) .childHandler(new ChannelInitializer() { @Override public void initChannel(SocketChannel ch) throws Exception { - ch.pipeline().addLast(// - new DefaultEventExecutorGroup(nettyServerConfig.getServerWorkerThreads()), // + ch.pipeline().addLast( + // + defaultEventExecutorGroup, // new NettyEncoder(), // new NettyDecoder(), // - new NettyConnetManageHandler(), new NettyServerHandler()); + new IdleStateHandler(0, 0, nettyServerConfig.getServerChannelMaxIdleTimeSeconds()),// + new NettyConnetManageHandler(), // + new NettyServerHandler()); } }); @@ -183,46 +146,42 @@ public void initChannel(SocketChannel ch) throws Exception { if (this.channelEventListener != null) { this.nettyEventExecuter.start(); } - } + // 每隔1秒扫描下异步调用超时情况 + this.timer.scheduleAtFixedRate(new TimerTask() { - @Override - public void shutdown() { - try { - this.serverBootstrap.shutdown(); - - if (this.nettyEventExecuter != null) { - this.nettyEventExecuter.shutdown(); - } - } - catch (Exception e) { - log.error("NettyRemotingServer shutdown exception, ", e); - } - - if (this.publicExecutor != null) { - try { - this.publicExecutor.shutdown(); - } - catch (Exception e) { - log.error("NettyRemotingServer shutdown exception, ", e); + @Override + public void run() { + try { + NettyRemotingServer.this.scanResponseTable(); + } + catch (Exception e) { + log.error("scanResponseTable exception", e); + } } - } + }, 1000 * 3, 1000); } @Override - public void registerProcessor(int requestCode, NettyRequestProcessor processor, Executor executor) { - Executor executorThis = executor; + public void registerProcessor(int requestCode, NettyRequestProcessor processor, ExecutorService executor) { + ExecutorService executorThis = executor; if (null == executor) { executorThis = this.publicExecutor; } - Pair pair = - new Pair(processor, executorThis); + Pair pair = + new Pair(processor, executorThis); this.processorTable.put(requestCode, pair); } + @Override + public void registerDefaultProcessor(NettyRequestProcessor processor, ExecutorService executor) { + this.defaultRequestProcessor = new Pair(processor, executor); + } + + @Override public RemotingCommand invokeSync(final Channel channel, final RemotingCommand request, final long timeoutMillis) throws InterruptedException, RemotingSendRequestException, @@ -248,14 +207,34 @@ public void invokeOneway(Channel channel, RemotingCommand request, long timeoutM @Override - public Executor getCallbackExecutor() { - return this.publicExecutor; - } + public void shutdown() { + try { + if (this.timer != null) { + this.timer.cancel(); + } + this.eventLoopGroup.shutdownGracefully(); - @Override - public void registerDefaultProcessor(NettyRequestProcessor processor, Executor executor) { - this.defaultRequestProcessor = new Pair(processor, executor); + if (this.nettyEventExecuter != null) { + this.nettyEventExecuter.shutdown(); + } + + if (this.defaultEventExecutorGroup != null) { + this.defaultEventExecutorGroup.shutdownGracefully(); + } + } + catch (Exception e) { + log.error("NettyRemotingServer shutdown exception, ", e); + } + + if (this.publicExecutor != null) { + try { + this.publicExecutor.shutdown(); + } + catch (Exception e) { + log.error("NettyRemotingServer shutdown exception, ", e); + } + } } @@ -263,4 +242,102 @@ public void registerDefaultProcessor(NettyRequestProcessor processor, Executor e public ChannelEventListener getChannelEventListener() { return channelEventListener; } + + + @Override + public ExecutorService getCallbackExecutor() { + return this.publicExecutor; + } + + class NettyServerHandler extends SimpleChannelInboundHandler { + + // @Override + // protected void messageReceived(ChannelHandlerContext ctx, + // RemotingCommand msg) throws Exception { + // processMessageReceived(ctx, msg); + // } + + @Override + protected void channelRead0(ChannelHandlerContext ctx, RemotingCommand msg) throws Exception { + processMessageReceived(ctx, msg); + + } + } + + class NettyConnetManageHandler extends ChannelDuplexHandler { + @Override + public void channelRegistered(ChannelHandlerContext ctx) throws Exception { + final String remoteAddress = RemotingHelper.parseChannelRemoteAddr(ctx.channel()); + log.info("NETTY SERVER PIPELINE: channelRegistered {}", remoteAddress); + super.channelRegistered(ctx); + } + + + @Override + public void channelUnregistered(ChannelHandlerContext ctx) throws Exception { + final String remoteAddress = RemotingHelper.parseChannelRemoteAddr(ctx.channel()); + log.info("NETTY SERVER PIPELINE: channelUnregistered, the channel[{}]", remoteAddress); + super.channelUnregistered(ctx); + } + + + @Override + public void channelActive(ChannelHandlerContext ctx) throws Exception { + final String remoteAddress = RemotingHelper.parseChannelRemoteAddr(ctx.channel()); + log.info("NETTY SERVER PIPELINE: channelActive, the channel[{}]", remoteAddress); + super.channelActive(ctx); + + if (NettyRemotingServer.this.channelEventListener != null) { + NettyRemotingServer.this.putNettyEvent(new NettyEvent(NettyEventType.CONNECT, remoteAddress + .toString(), ctx.channel())); + } + } + + + @Override + public void channelInactive(ChannelHandlerContext ctx) throws Exception { + final String remoteAddress = RemotingHelper.parseChannelRemoteAddr(ctx.channel()); + log.info("NETTY SERVER PIPELINE: channelInactive, the channel[{}]", remoteAddress); + super.channelInactive(ctx); + + if (NettyRemotingServer.this.channelEventListener != null) { + NettyRemotingServer.this.putNettyEvent(new NettyEvent(NettyEventType.CLOSE, remoteAddress + .toString(), ctx.channel())); + } + } + + + @Override + public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception { + if (evt instanceof IdleStateEvent) { + IdleStateEvent evnet = (IdleStateEvent) evt; + if (evnet.state().equals(IdleState.ALL_IDLE)) { + final String remoteAddress = RemotingHelper.parseChannelRemoteAddr(ctx.channel()); + log.warn("NETTY SERVER PIPELINE: IDLE exception [{}]", remoteAddress); + RemotingUtil.closeChannel(ctx.channel()); + if (NettyRemotingServer.this.channelEventListener != null) { + NettyRemotingServer.this.putNettyEvent(new NettyEvent(NettyEventType.IDLE, + remoteAddress.toString(), ctx.channel())); + } + } + } + + ctx.fireUserEventTriggered(evt); + } + + + @Override + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { + final String remoteAddress = RemotingHelper.parseChannelRemoteAddr(ctx.channel()); + log.warn("NETTY SERVER PIPELINE: exceptionCaught {}", remoteAddress); + log.warn("NETTY SERVER PIPELINE: exceptionCaught exception.", cause); + + if (NettyRemotingServer.this.channelEventListener != null) { + NettyRemotingServer.this.putNettyEvent(new NettyEvent(NettyEventType.EXCEPTION, remoteAddress + .toString(), ctx.channel())); + } + + RemotingUtil.closeChannel(ctx.channel()); + } + } } diff --git a/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/netty/NettyRequestProcessor.java b/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/netty/NettyRequestProcessor.java index b33fd1a9..296a0f0b 100644 --- a/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/netty/NettyRequestProcessor.java +++ b/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/netty/NettyRequestProcessor.java @@ -1,5 +1,17 @@ /** - * $Id: NettyRequestProcessor.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.remoting.netty; @@ -10,9 +22,10 @@ /** + * 接收请求处理器,服务器与客户端通用 * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com - * + * @author shijia.wxr + * @since 2013-7-13 */ public interface NettyRequestProcessor { public RemotingCommand processRequest(ChannelHandlerContext ctx, RemotingCommand request) diff --git a/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/netty/NettyServerConfig.java b/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/netty/NettyServerConfig.java index a1361f14..d0e8f4ca 100644 --- a/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/netty/NettyServerConfig.java +++ b/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/netty/NettyServerConfig.java @@ -1,11 +1,25 @@ /** - * $Id: NettyServerConfig.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.remoting.netty; /** - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * Netty服务端配置 * + * @author shijia.wxr + * @since 2013-7-13 */ public class NettyServerConfig { private int listenPort = 8888; @@ -14,6 +28,7 @@ public class NettyServerConfig { private int serverSelectorThreads = 8; private int serverOnewaySemaphoreValue = 32; private int serverAsyncSemaphoreValue = 64; + private int serverChannelMaxIdleTimeSeconds = 120; public int getListenPort() { @@ -74,4 +89,14 @@ public int getServerAsyncSemaphoreValue() { public void setServerAsyncSemaphoreValue(int serverAsyncSemaphoreValue) { this.serverAsyncSemaphoreValue = serverAsyncSemaphoreValue; } + + + public int getServerChannelMaxIdleTimeSeconds() { + return serverChannelMaxIdleTimeSeconds; + } + + + public void setServerChannelMaxIdleTimeSeconds(int serverChannelMaxIdleTimeSeconds) { + this.serverChannelMaxIdleTimeSeconds = serverChannelMaxIdleTimeSeconds; + } } diff --git a/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/netty/ResponseFuture.java b/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/netty/ResponseFuture.java index e0cf19af..e9c896a9 100644 --- a/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/netty/ResponseFuture.java +++ b/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/netty/ResponseFuture.java @@ -1,11 +1,23 @@ /** - * $Id: ResponseFuture.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.remoting.netty; import java.util.concurrent.CountDownLatch; -import java.util.concurrent.Semaphore; import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; import com.alibaba.rocketmq.remoting.InvokeCallback; import com.alibaba.rocketmq.remoting.common.SemaphoreReleaseOnlyOnce; @@ -13,9 +25,10 @@ /** + * 异步请求应答封装 * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com - * + * @author shijia.wxr + * @since 2013-7-13 */ public class ResponseFuture { private volatile RemotingCommand responseCommand; @@ -26,8 +39,13 @@ public class ResponseFuture { private final InvokeCallback invokeCallback; private final long beginTimestamp = System.currentTimeMillis(); private final CountDownLatch countDownLatch = new CountDownLatch(1); + + // 保证信号量至多至少只被释放一次 private final SemaphoreReleaseOnlyOnce once; + // 保证回调的callback方法至多至少只被执行一次 + private final AtomicBoolean executeCallbackOnlyOnce = new AtomicBoolean(false); + public ResponseFuture(int opaque, long timeoutMillis, InvokeCallback invokeCallback, SemaphoreReleaseOnlyOnce once) { @@ -38,6 +56,15 @@ public ResponseFuture(int opaque, long timeoutMillis, InvokeCallback invokeCallb } + public void executeInvokeCallback() { + if (invokeCallback != null) { + if (this.executeCallbackOnlyOnce.compareAndSet(false, true)) { + invokeCallback.operationComplete(this); + } + } + } + + public void release() { if (this.once != null) { this.once.release(); diff --git a/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/protocol/LanguageCode.java b/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/protocol/LanguageCode.java new file mode 100644 index 00000000..1ec08984 --- /dev/null +++ b/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/protocol/LanguageCode.java @@ -0,0 +1,12 @@ +package com.alibaba.rocketmq.remoting.protocol; + +public enum LanguageCode { + JAVA, + CPP, + DOTNET, + PYTHON, + DELPHI, + ERLANG, + RUBY, + OTHER, +} diff --git a/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/protocol/RemotingCommand.java b/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/protocol/RemotingCommand.java index 4aad2406..8aaa3b10 100644 --- a/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/protocol/RemotingCommand.java +++ b/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/protocol/RemotingCommand.java @@ -1,5 +1,17 @@ /** - * $Id: RemotingCommand.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.remoting.protocol; @@ -7,33 +19,37 @@ import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.nio.ByteBuffer; -import java.util.ArrayList; -import java.util.List; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map.Entry; import java.util.concurrent.atomic.AtomicInteger; +import com.alibaba.fastjson.annotation.JSONField; import com.alibaba.rocketmq.remoting.CommandCustomHeader; import com.alibaba.rocketmq.remoting.annotation.CFNotNull; import com.alibaba.rocketmq.remoting.exception.RemotingCommandException; -import com.alibaba.rocketmq.remoting.protocol.RemotingProtos.CommandHeader; -import com.alibaba.rocketmq.remoting.protocol.RemotingProtos.FlagBit; -import com.alibaba.rocketmq.remoting.protocol.RemotingProtos.LanguageCode; -import com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPair; import com.alibaba.rocketmq.remoting.protocol.RemotingProtos.ResponseCode; -import com.google.protobuf.InvalidProtocolBufferException; /** - * RPC Ӧ + * Remoting模块中,服务器与客户端通过传递RemotingCommand来交互 * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * @author shijia.wxr + * @since 2013-7-13 */ public class RemotingCommand { public static String RemotingVersionKey = "rocketmq.remoting.version"; private static volatile int ConfigVersion = -1; private static AtomicInteger RequestId = new AtomicInteger(0); + private static final int RPC_TYPE = 0; // 0, REQUEST_COMMAND + // 1, RESPONSE_COMMAND + + private static final int RPC_ONEWAY = 1; // 0, RPC + // 1, Oneway + /** - * Header + * Header 部分 */ private int code; private LanguageCode language = LanguageCode.JAVA; @@ -41,13 +57,14 @@ public class RemotingCommand { private int opaque = RequestId.getAndIncrement(); private int flag = 0; private String remark; - private List extFields; - private CommandCustomHeader customHeader; + private HashMap extFields; + + private transient CommandCustomHeader customHeader; /** - * Body + * Body 部分 */ - private byte[] body; + private transient byte[] body; protected RemotingCommand() { @@ -65,7 +82,8 @@ public static RemotingCommand createRequestCommand(int code, CommandCustomHeader public static RemotingCommand createResponseCommand(Class classHeader) { RemotingCommand cmd = - createResponseCommand(ResponseCode.SYSTEM_ERROR_VALUE, "not set any response code", classHeader); + createResponseCommand(ResponseCode.SYSTEM_ERROR_VALUE, "not set any response code", + classHeader); return cmd; } @@ -77,7 +95,7 @@ public static RemotingCommand createResponseCommand(int code, String remark) { /** - * ֻͨŲڲãҵ񲻻 + * 只有通信层内部会调用,业务不会调用 */ public static RemotingCommand createResponseCommand(int code, String remark, Class classHeader) { @@ -122,7 +140,7 @@ private static void setCmdVersion(RemotingCommand cmd) { private void makeCustomHeaderToNet() { if (this.customHeader != null) { Field[] fields = this.customHeader.getClass().getDeclaredFields(); - this.extFields = new ArrayList(fields.length); + this.extFields = new HashMap(); for (Field field : fields) { if (!Modifier.isStatic(field.getModifiers())) { String name = field.getName(); @@ -138,10 +156,7 @@ private void makeCustomHeaderToNet() { } if (value != null) { - NVPair.Builder nvb = NVPair.newBuilder(); - nvb.setName(name); - nvb.setValue(value.toString()); - this.extFields.add(nvb.build()); + this.extFields.put(name, value.toString()); } } } @@ -169,9 +184,11 @@ public CommandCustomHeader decodeCommandCustomHeader(Class> it = this.extFields.entrySet().iterator(); + while (it.hasNext()) { + Entry entry = it.next(); + String name = entry.getKey(); + String value = entry.getValue(); try { Field field = objectHeader.getClass().getDeclaredField(name); @@ -219,7 +236,7 @@ else if (type.equals("double")) { } } - // 鷵ضǷЧ + // 检查返回对象是否有效 Field[] fields = objectHeader.getClass().getDeclaredFields(); for (Field field : fields) { if (!Modifier.isStatic(field.getModifiers())) { @@ -235,14 +252,11 @@ else if (type.equals("double")) { catch (IllegalAccessException e) { } - // ֵ + // 空值检查 if (null == value) { - Annotation[] ann = field.getAnnotations(); - if (ann != null && ann.length > 0) { - if (ann[0].annotationType().getSimpleName() - .equalsIgnoreCase(CFNotNull.class.getSimpleName())) { - throw new RemotingCommandException(name + " is null"); - } + Annotation annotation = field.getAnnotation(CFNotNull.class); + if (annotation != null) { + throw new RemotingCommandException("the custom field <" + name + "> is null"); } } } @@ -258,40 +272,18 @@ else if (type.equals("double")) { } - private CommandHeader buildHeader() { - CommandHeader.Builder builder = CommandHeader.newBuilder(); - builder.setCode(this.code); - builder.setLanguage(this.language); - builder.setVersion(this.version); - builder.setOpaque(this.opaque); - builder.setFlag(this.flag); - if (this.remark != null) { - builder.setRemark(this.remark); - } - - // customHeader + private byte[] buildHeader() { this.makeCustomHeaderToNet(); - - // extFields - if (this.extFields != null) { - int i = 0; - for (NVPair nv : this.extFields) { - builder.addExtFields(i++, nv); - } - } - - return builder.build(); + return RemotingSerializable.encode(this); } public ByteBuffer encode() { - CommandHeader header = this.buildHeader(); - // 1> header length size int length = 4; // 2> header data length - byte[] headerData = header.toByteArray(); + byte[] headerData = this.buildHeader(); length += headerData.length; // 3> body data length @@ -327,16 +319,14 @@ public ByteBuffer encodeHeader() { /** - * ֻHeaderbodyֶ + * 只打包Header,body部分独立传输 */ public ByteBuffer encodeHeader(final int bodyLength) { - CommandHeader header = this.buildHeader(); - // 1> header length size int length = 4; // 2> header data length - byte[] headerData = header.toByteArray(); + byte[] headerData = this.buildHeader(); length += headerData.length; // 3> body data length @@ -359,13 +349,13 @@ public ByteBuffer encodeHeader(final int bodyLength) { } - public static RemotingCommand decode(final byte[] array) throws InvalidProtocolBufferException { + public static RemotingCommand decode(final byte[] array) { ByteBuffer byteBuffer = ByteBuffer.wrap(array); return decode(byteBuffer); } - public static RemotingCommand decode(final ByteBuffer byteBuffer) throws InvalidProtocolBufferException { + public static RemotingCommand decode(final ByteBuffer byteBuffer) { int length = byteBuffer.limit(); int headerLength = byteBuffer.getInt(); @@ -379,19 +369,7 @@ public static RemotingCommand decode(final ByteBuffer byteBuffer) throws Invalid byteBuffer.get(bodyData); } - RemotingCommand cmd = new RemotingCommand(); - CommandHeader header = CommandHeader.parseFrom(headerData); - - cmd.code = header.getCode(); - cmd.language = header.getLanguage(); - cmd.version = header.getVersion(); - cmd.opaque = header.getOpaque(); - cmd.flag = header.getFlag(); - if (header.hasRemark()) - cmd.remark = header.getRemark(); - - cmd.extFields = header.getExtFieldsList(); - + RemotingCommand cmd = RemotingSerializable.decode(headerData, RemotingCommand.class); cmd.body = bodyData; return cmd; @@ -399,25 +377,27 @@ public static RemotingCommand decode(final ByteBuffer byteBuffer) throws Invalid public void markResponseType() { - int bits = 1 << FlagBit.RPC_TYPE_VALUE; + int bits = 1 << RPC_TYPE; this.flag |= bits; } + @JSONField(serialize = false) public boolean isResponseType() { - int bits = 1 << FlagBit.RPC_TYPE_VALUE; + int bits = 1 << RPC_TYPE; return (this.flag & bits) == bits; } public void markOnewayRPC() { - int bits = 1 << FlagBit.RPC_ONEWAY_VALUE; + int bits = 1 << RPC_ONEWAY; this.flag |= bits; } + @JSONField(serialize = false) public boolean isOnewayRPC() { - int bits = 1 << FlagBit.RPC_ONEWAY_VALUE; + int bits = 1 << RPC_ONEWAY; return (this.flag & bits) == bits; } @@ -432,6 +412,7 @@ public void setCode(int code) { } + @JSONField(serialize = false) public RemotingCommandType getType() { if (this.isResponseType()) { return RemotingCommandType.RESPONSE_COMMAND; @@ -501,30 +482,20 @@ public void setBody(byte[] body) { } - public List getExtFields() { + public HashMap getExtFields() { return extFields; } - public void setExtFields(List extFields) { + public void setExtFields(HashMap extFields) { this.extFields = extFields; } @Override public String toString() { - return "RemotingCommand [code=" + code + ", language=" + language + ", version=" + version + ", opaque=" - + opaque + ", flag(B)=" + Integer.toBinaryString(flag) + ", remark=" + remark + ", extFields=" - + extFields + "]"; + return "RemotingCommand [code=" + code + ", language=" + language + ", version=" + version + + ", opaque=" + opaque + ", flag(B)=" + Integer.toBinaryString(flag) + ", remark=" + remark + + ", extFields=" + extFields + "]"; } - - // public CommandCustomHeader getCustomHeader() { - // return customHeader; - // } - // - // - // public void setCustomHeader(CommandCustomHeader customHeader) { - // this.customHeader = customHeader; - // } - } diff --git a/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/protocol/RemotingCommandType.java b/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/protocol/RemotingCommandType.java index d7d17c08..d287d145 100644 --- a/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/protocol/RemotingCommandType.java +++ b/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/protocol/RemotingCommandType.java @@ -1,13 +1,25 @@ /** - * $Id: RemotingCommandType.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.remoting.protocol; /** - * ͣӦ - * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * 标识RemotingCommand是请求还是应答类型 * + * @author shijia.wxr + * @since 2013-7-13 */ public enum RemotingCommandType { REQUEST_COMMAND, diff --git a/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/protocol/RemotingProtos.java b/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/protocol/RemotingProtos.java index 0a34a24f..bd5b94ca 100644 --- a/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/protocol/RemotingProtos.java +++ b/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/protocol/RemotingProtos.java @@ -1,3872 +1,64 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// source: remoting.proto - package com.alibaba.rocketmq.remoting.protocol; public final class RemotingProtos { - private RemotingProtos() {} - public static void registerAllExtensions( - com.google.protobuf.ExtensionRegistry registry) { - } - public enum LanguageCode - implements com.google.protobuf.ProtocolMessageEnum { - JAVA(0, 0), - CPP(1, 1), - DOTNET(2, 2), - PYTHON(3, 3), - DELPHI(4, 4), - ERLANG(5, 5), - RUBY(6, 6), - OTHER(7, 7), - ; - - public static final int JAVA_VALUE = 0; - public static final int CPP_VALUE = 1; - public static final int DOTNET_VALUE = 2; - public static final int PYTHON_VALUE = 3; - public static final int DELPHI_VALUE = 4; - public static final int ERLANG_VALUE = 5; - public static final int RUBY_VALUE = 6; - public static final int OTHER_VALUE = 7; - - - public final int getNumber() { return value; } - - public static LanguageCode valueOf(int value) { - switch (value) { - case 0: return JAVA; - case 1: return CPP; - case 2: return DOTNET; - case 3: return PYTHON; - case 4: return DELPHI; - case 5: return ERLANG; - case 6: return RUBY; - case 7: return OTHER; - default: return null; - } - } - - public static com.google.protobuf.Internal.EnumLiteMap - internalGetValueMap() { - return internalValueMap; - } - private static com.google.protobuf.Internal.EnumLiteMap - internalValueMap = - new com.google.protobuf.Internal.EnumLiteMap() { - public LanguageCode findValueByNumber(int number) { - return LanguageCode.valueOf(number); - } - }; - - public final com.google.protobuf.Descriptors.EnumValueDescriptor - getValueDescriptor() { - return getDescriptor().getValues().get(index); - } - public final com.google.protobuf.Descriptors.EnumDescriptor - getDescriptorForType() { - return getDescriptor(); - } - public static final com.google.protobuf.Descriptors.EnumDescriptor - getDescriptor() { - return com.alibaba.rocketmq.remoting.protocol.RemotingProtos.getDescriptor().getEnumTypes().get(0); - } - - private static final LanguageCode[] VALUES = { - JAVA, CPP, DOTNET, PYTHON, DELPHI, ERLANG, RUBY, OTHER, - }; - - public static LanguageCode valueOf( - com.google.protobuf.Descriptors.EnumValueDescriptor desc) { - if (desc.getType() != getDescriptor()) { - throw new java.lang.IllegalArgumentException( - "EnumValueDescriptor is not for this type."); - } - return VALUES[desc.getIndex()]; - } - - private final int index; - private final int value; - - private LanguageCode(int index, int value) { - this.index = index; - this.value = value; - } - - // @@protoc_insertion_point(enum_scope:remoting.LanguageCode) - } - - public enum FlagBit - implements com.google.protobuf.ProtocolMessageEnum { - RPC_TYPE(0, 0), - RPC_ONEWAY(1, 1), - ; - - public static final int RPC_TYPE_VALUE = 0; - public static final int RPC_ONEWAY_VALUE = 1; - - - public final int getNumber() { return value; } - - public static FlagBit valueOf(int value) { - switch (value) { - case 0: return RPC_TYPE; - case 1: return RPC_ONEWAY; - default: return null; - } - } - - public static com.google.protobuf.Internal.EnumLiteMap - internalGetValueMap() { - return internalValueMap; - } - private static com.google.protobuf.Internal.EnumLiteMap - internalValueMap = - new com.google.protobuf.Internal.EnumLiteMap() { - public FlagBit findValueByNumber(int number) { - return FlagBit.valueOf(number); - } - }; - - public final com.google.protobuf.Descriptors.EnumValueDescriptor - getValueDescriptor() { - return getDescriptor().getValues().get(index); - } - public final com.google.protobuf.Descriptors.EnumDescriptor - getDescriptorForType() { - return getDescriptor(); - } - public static final com.google.protobuf.Descriptors.EnumDescriptor - getDescriptor() { - return com.alibaba.rocketmq.remoting.protocol.RemotingProtos.getDescriptor().getEnumTypes().get(1); - } - - private static final FlagBit[] VALUES = { - RPC_TYPE, RPC_ONEWAY, - }; - - public static FlagBit valueOf( - com.google.protobuf.Descriptors.EnumValueDescriptor desc) { - if (desc.getType() != getDescriptor()) { - throw new java.lang.IllegalArgumentException( - "EnumValueDescriptor is not for this type."); - } - return VALUES[desc.getIndex()]; - } - - private final int index; - private final int value; - - private FlagBit(int index, int value) { - this.index = index; - this.value = value; - } - - // @@protoc_insertion_point(enum_scope:remoting.FlagBit) - } - - public enum RequestCode - implements com.google.protobuf.ProtocolMessageEnum { - DEMO_REQUEST(0, 0), - ; - - public static final int DEMO_REQUEST_VALUE = 0; - - - public final int getNumber() { return value; } - - public static RequestCode valueOf(int value) { - switch (value) { - case 0: return DEMO_REQUEST; - default: return null; - } - } - - public static com.google.protobuf.Internal.EnumLiteMap - internalGetValueMap() { - return internalValueMap; - } - private static com.google.protobuf.Internal.EnumLiteMap - internalValueMap = - new com.google.protobuf.Internal.EnumLiteMap() { - public RequestCode findValueByNumber(int number) { - return RequestCode.valueOf(number); - } - }; - - public final com.google.protobuf.Descriptors.EnumValueDescriptor - getValueDescriptor() { - return getDescriptor().getValues().get(index); - } - public final com.google.protobuf.Descriptors.EnumDescriptor - getDescriptorForType() { - return getDescriptor(); - } - public static final com.google.protobuf.Descriptors.EnumDescriptor - getDescriptor() { - return com.alibaba.rocketmq.remoting.protocol.RemotingProtos.getDescriptor().getEnumTypes().get(2); - } - - private static final RequestCode[] VALUES = { - DEMO_REQUEST, - }; - - public static RequestCode valueOf( - com.google.protobuf.Descriptors.EnumValueDescriptor desc) { - if (desc.getType() != getDescriptor()) { - throw new java.lang.IllegalArgumentException( - "EnumValueDescriptor is not for this type."); - } - return VALUES[desc.getIndex()]; - } - - private final int index; - private final int value; - - private RequestCode(int index, int value) { - this.index = index; - this.value = value; - } - - // @@protoc_insertion_point(enum_scope:remoting.RequestCode) - } - - public enum ResponseCode - implements com.google.protobuf.ProtocolMessageEnum { - SUCCESS(0, 0), - SYSTEM_ERROR(1, 1), - SYSTEM_BUSY(2, 2), - REQUEST_CODE_NOT_SUPPORTED(3, 3), - ; - - public static final int SUCCESS_VALUE = 0; - public static final int SYSTEM_ERROR_VALUE = 1; - public static final int SYSTEM_BUSY_VALUE = 2; - public static final int REQUEST_CODE_NOT_SUPPORTED_VALUE = 3; - - - public final int getNumber() { return value; } - - public static ResponseCode valueOf(int value) { - switch (value) { - case 0: return SUCCESS; - case 1: return SYSTEM_ERROR; - case 2: return SYSTEM_BUSY; - case 3: return REQUEST_CODE_NOT_SUPPORTED; - default: return null; - } - } - - public static com.google.protobuf.Internal.EnumLiteMap - internalGetValueMap() { - return internalValueMap; - } - private static com.google.protobuf.Internal.EnumLiteMap - internalValueMap = - new com.google.protobuf.Internal.EnumLiteMap() { - public ResponseCode findValueByNumber(int number) { - return ResponseCode.valueOf(number); - } - }; - - public final com.google.protobuf.Descriptors.EnumValueDescriptor - getValueDescriptor() { - return getDescriptor().getValues().get(index); - } - public final com.google.protobuf.Descriptors.EnumDescriptor - getDescriptorForType() { - return getDescriptor(); - } - public static final com.google.protobuf.Descriptors.EnumDescriptor - getDescriptor() { - return com.alibaba.rocketmq.remoting.protocol.RemotingProtos.getDescriptor().getEnumTypes().get(3); - } - - private static final ResponseCode[] VALUES = { - SUCCESS, SYSTEM_ERROR, SYSTEM_BUSY, REQUEST_CODE_NOT_SUPPORTED, - }; - - public static ResponseCode valueOf( - com.google.protobuf.Descriptors.EnumValueDescriptor desc) { - if (desc.getType() != getDescriptor()) { - throw new java.lang.IllegalArgumentException( - "EnumValueDescriptor is not for this type."); - } - return VALUES[desc.getIndex()]; - } - - private final int index; - private final int value; - - private ResponseCode(int index, int value) { - this.index = index; - this.value = value; - } - - // @@protoc_insertion_point(enum_scope:remoting.ResponseCode) - } - - public interface KVPairOrBuilder - extends com.google.protobuf.MessageOrBuilder { - - // required int32 key = 1; - boolean hasKey(); - int getKey(); - - // required string value = 2; - boolean hasValue(); - String getValue(); - } - public static final class KVPair extends - com.google.protobuf.GeneratedMessage - implements KVPairOrBuilder { - // Use KVPair.newBuilder() to construct. - private KVPair(Builder builder) { - super(builder); - } - private KVPair(boolean noInit) {} - - private static final KVPair defaultInstance; - public static KVPair getDefaultInstance() { - return defaultInstance; - } - - public KVPair getDefaultInstanceForType() { - return defaultInstance; - } - - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return com.alibaba.rocketmq.remoting.protocol.RemotingProtos.internal_static_remoting_KVPair_descriptor; - } - - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return com.alibaba.rocketmq.remoting.protocol.RemotingProtos.internal_static_remoting_KVPair_fieldAccessorTable; - } - - private int bitField0_; - // required int32 key = 1; - public static final int KEY_FIELD_NUMBER = 1; - private int key_; - public boolean hasKey() { - return ((bitField0_ & 0x00000001) == 0x00000001); - } - public int getKey() { - return key_; - } - - // required string value = 2; - public static final int VALUE_FIELD_NUMBER = 2; - private java.lang.Object value_; - public boolean hasValue() { - return ((bitField0_ & 0x00000002) == 0x00000002); - } - public String getValue() { - java.lang.Object ref = value_; - if (ref instanceof String) { - return (String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - String s = bs.toStringUtf8(); - if (com.google.protobuf.Internal.isValidUtf8(bs)) { - value_ = s; - } - return s; - } - } - private com.google.protobuf.ByteString getValueBytes() { - java.lang.Object ref = value_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8((String) ref); - value_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - private void initFields() { - key_ = 0; - value_ = ""; - } - private byte memoizedIsInitialized = -1; - public final boolean isInitialized() { - byte isInitialized = memoizedIsInitialized; - if (isInitialized != -1) return isInitialized == 1; - - if (!hasKey()) { - memoizedIsInitialized = 0; - return false; - } - if (!hasValue()) { - memoizedIsInitialized = 0; - return false; - } - memoizedIsInitialized = 1; - return true; - } - - public void writeTo(com.google.protobuf.CodedOutputStream output) - throws java.io.IOException { - getSerializedSize(); - if (((bitField0_ & 0x00000001) == 0x00000001)) { - output.writeInt32(1, key_); - } - if (((bitField0_ & 0x00000002) == 0x00000002)) { - output.writeBytes(2, getValueBytes()); - } - getUnknownFields().writeTo(output); - } - - private int memoizedSerializedSize = -1; - public int getSerializedSize() { - int size = memoizedSerializedSize; - if (size != -1) return size; - - size = 0; - if (((bitField0_ & 0x00000001) == 0x00000001)) { - size += com.google.protobuf.CodedOutputStream - .computeInt32Size(1, key_); - } - if (((bitField0_ & 0x00000002) == 0x00000002)) { - size += com.google.protobuf.CodedOutputStream - .computeBytesSize(2, getValueBytes()); - } - size += getUnknownFields().getSerializedSize(); - memoizedSerializedSize = size; - return size; - } - - private static final long serialVersionUID = 0L; - @java.lang.Override - protected java.lang.Object writeReplace() - throws java.io.ObjectStreamException { - return super.writeReplace(); - } - - public static com.alibaba.rocketmq.remoting.protocol.RemotingProtos.KVPair parseFrom( - com.google.protobuf.ByteString data) - throws com.google.protobuf.InvalidProtocolBufferException { - return newBuilder().mergeFrom(data).buildParsed(); - } - public static com.alibaba.rocketmq.remoting.protocol.RemotingProtos.KVPair parseFrom( - com.google.protobuf.ByteString data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return newBuilder().mergeFrom(data, extensionRegistry) - .buildParsed(); - } - public static com.alibaba.rocketmq.remoting.protocol.RemotingProtos.KVPair parseFrom(byte[] data) - throws com.google.protobuf.InvalidProtocolBufferException { - return newBuilder().mergeFrom(data).buildParsed(); - } - public static com.alibaba.rocketmq.remoting.protocol.RemotingProtos.KVPair parseFrom( - byte[] data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return newBuilder().mergeFrom(data, extensionRegistry) - .buildParsed(); - } - public static com.alibaba.rocketmq.remoting.protocol.RemotingProtos.KVPair parseFrom(java.io.InputStream input) - throws java.io.IOException { - return newBuilder().mergeFrom(input).buildParsed(); - } - public static com.alibaba.rocketmq.remoting.protocol.RemotingProtos.KVPair parseFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return newBuilder().mergeFrom(input, extensionRegistry) - .buildParsed(); - } - public static com.alibaba.rocketmq.remoting.protocol.RemotingProtos.KVPair parseDelimitedFrom(java.io.InputStream input) - throws java.io.IOException { - Builder builder = newBuilder(); - if (builder.mergeDelimitedFrom(input)) { - return builder.buildParsed(); - } else { - return null; - } - } - public static com.alibaba.rocketmq.remoting.protocol.RemotingProtos.KVPair parseDelimitedFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - Builder builder = newBuilder(); - if (builder.mergeDelimitedFrom(input, extensionRegistry)) { - return builder.buildParsed(); - } else { - return null; - } - } - public static com.alibaba.rocketmq.remoting.protocol.RemotingProtos.KVPair parseFrom( - com.google.protobuf.CodedInputStream input) - throws java.io.IOException { - return newBuilder().mergeFrom(input).buildParsed(); - } - public static com.alibaba.rocketmq.remoting.protocol.RemotingProtos.KVPair parseFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return newBuilder().mergeFrom(input, extensionRegistry) - .buildParsed(); - } - - public static Builder newBuilder() { return Builder.create(); } - public Builder newBuilderForType() { return newBuilder(); } - public static Builder newBuilder(com.alibaba.rocketmq.remoting.protocol.RemotingProtos.KVPair prototype) { - return newBuilder().mergeFrom(prototype); - } - public Builder toBuilder() { return newBuilder(this); } - - @java.lang.Override - protected Builder newBuilderForType( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - Builder builder = new Builder(parent); - return builder; - } - public static final class Builder extends - com.google.protobuf.GeneratedMessage.Builder - implements com.alibaba.rocketmq.remoting.protocol.RemotingProtos.KVPairOrBuilder { - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return com.alibaba.rocketmq.remoting.protocol.RemotingProtos.internal_static_remoting_KVPair_descriptor; - } - - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return com.alibaba.rocketmq.remoting.protocol.RemotingProtos.internal_static_remoting_KVPair_fieldAccessorTable; - } - - // Construct using com.alibaba.rocketmq.remoting.protocol.RemotingProtos.KVPair.newBuilder() - private Builder() { - maybeForceBuilderInitialization(); - } - - private Builder(BuilderParent parent) { - super(parent); - maybeForceBuilderInitialization(); - } - private void maybeForceBuilderInitialization() { - if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) { - } - } - private static Builder create() { - return new Builder(); - } - - public Builder clear() { - super.clear(); - key_ = 0; - bitField0_ = (bitField0_ & ~0x00000001); - value_ = ""; - bitField0_ = (bitField0_ & ~0x00000002); - return this; - } - - public Builder clone() { - return create().mergeFrom(buildPartial()); - } - - public com.google.protobuf.Descriptors.Descriptor - getDescriptorForType() { - return com.alibaba.rocketmq.remoting.protocol.RemotingProtos.KVPair.getDescriptor(); - } - - public com.alibaba.rocketmq.remoting.protocol.RemotingProtos.KVPair getDefaultInstanceForType() { - return com.alibaba.rocketmq.remoting.protocol.RemotingProtos.KVPair.getDefaultInstance(); - } - - public com.alibaba.rocketmq.remoting.protocol.RemotingProtos.KVPair build() { - com.alibaba.rocketmq.remoting.protocol.RemotingProtos.KVPair result = buildPartial(); - if (!result.isInitialized()) { - throw newUninitializedMessageException(result); - } - return result; - } - - private com.alibaba.rocketmq.remoting.protocol.RemotingProtos.KVPair buildParsed() - throws com.google.protobuf.InvalidProtocolBufferException { - com.alibaba.rocketmq.remoting.protocol.RemotingProtos.KVPair result = buildPartial(); - if (!result.isInitialized()) { - throw newUninitializedMessageException( - result).asInvalidProtocolBufferException(); - } - return result; - } - - public com.alibaba.rocketmq.remoting.protocol.RemotingProtos.KVPair buildPartial() { - com.alibaba.rocketmq.remoting.protocol.RemotingProtos.KVPair result = new com.alibaba.rocketmq.remoting.protocol.RemotingProtos.KVPair(this); - int from_bitField0_ = bitField0_; - int to_bitField0_ = 0; - if (((from_bitField0_ & 0x00000001) == 0x00000001)) { - to_bitField0_ |= 0x00000001; - } - result.key_ = key_; - if (((from_bitField0_ & 0x00000002) == 0x00000002)) { - to_bitField0_ |= 0x00000002; - } - result.value_ = value_; - result.bitField0_ = to_bitField0_; - onBuilt(); - return result; - } - - public Builder mergeFrom(com.google.protobuf.Message other) { - if (other instanceof com.alibaba.rocketmq.remoting.protocol.RemotingProtos.KVPair) { - return mergeFrom((com.alibaba.rocketmq.remoting.protocol.RemotingProtos.KVPair)other); - } else { - super.mergeFrom(other); - return this; - } - } - - public Builder mergeFrom(com.alibaba.rocketmq.remoting.protocol.RemotingProtos.KVPair other) { - if (other == com.alibaba.rocketmq.remoting.protocol.RemotingProtos.KVPair.getDefaultInstance()) return this; - if (other.hasKey()) { - setKey(other.getKey()); - } - if (other.hasValue()) { - setValue(other.getValue()); - } - this.mergeUnknownFields(other.getUnknownFields()); - return this; - } - - public final boolean isInitialized() { - if (!hasKey()) { - - return false; - } - if (!hasValue()) { - - return false; - } - return true; - } - - public Builder mergeFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - com.google.protobuf.UnknownFieldSet.Builder unknownFields = - com.google.protobuf.UnknownFieldSet.newBuilder( - this.getUnknownFields()); - while (true) { - int tag = input.readTag(); - switch (tag) { - case 0: - this.setUnknownFields(unknownFields.build()); - onChanged(); - return this; - default: { - if (!parseUnknownField(input, unknownFields, - extensionRegistry, tag)) { - this.setUnknownFields(unknownFields.build()); - onChanged(); - return this; - } - break; - } - case 8: { - bitField0_ |= 0x00000001; - key_ = input.readInt32(); - break; - } - case 18: { - bitField0_ |= 0x00000002; - value_ = input.readBytes(); - break; - } - } - } - } - - private int bitField0_; - - // required int32 key = 1; - private int key_ ; - public boolean hasKey() { - return ((bitField0_ & 0x00000001) == 0x00000001); - } - public int getKey() { - return key_; - } - public Builder setKey(int value) { - bitField0_ |= 0x00000001; - key_ = value; - onChanged(); - return this; - } - public Builder clearKey() { - bitField0_ = (bitField0_ & ~0x00000001); - key_ = 0; - onChanged(); - return this; - } - - // required string value = 2; - private java.lang.Object value_ = ""; - public boolean hasValue() { - return ((bitField0_ & 0x00000002) == 0x00000002); - } - public String getValue() { - java.lang.Object ref = value_; - if (!(ref instanceof String)) { - String s = ((com.google.protobuf.ByteString) ref).toStringUtf8(); - value_ = s; - return s; - } else { - return (String) ref; - } - } - public Builder setValue(String value) { - if (value == null) { - throw new NullPointerException(); - } - bitField0_ |= 0x00000002; - value_ = value; - onChanged(); - return this; - } - public Builder clearValue() { - bitField0_ = (bitField0_ & ~0x00000002); - value_ = getDefaultInstance().getValue(); - onChanged(); - return this; - } - void setValue(com.google.protobuf.ByteString value) { - bitField0_ |= 0x00000002; - value_ = value; - onChanged(); - } - - // @@protoc_insertion_point(builder_scope:remoting.KVPair) - } - - static { - defaultInstance = new KVPair(true); - defaultInstance.initFields(); - } - - // @@protoc_insertion_point(class_scope:remoting.KVPair) - } - - public interface KVPairListOrBuilder - extends com.google.protobuf.MessageOrBuilder { - - // repeated .remoting.KVPair fields = 1; - java.util.List - getFieldsList(); - com.alibaba.rocketmq.remoting.protocol.RemotingProtos.KVPair getFields(int index); - int getFieldsCount(); - java.util.List - getFieldsOrBuilderList(); - com.alibaba.rocketmq.remoting.protocol.RemotingProtos.KVPairOrBuilder getFieldsOrBuilder( - int index); - } - public static final class KVPairList extends - com.google.protobuf.GeneratedMessage - implements KVPairListOrBuilder { - // Use KVPairList.newBuilder() to construct. - private KVPairList(Builder builder) { - super(builder); - } - private KVPairList(boolean noInit) {} - - private static final KVPairList defaultInstance; - public static KVPairList getDefaultInstance() { - return defaultInstance; - } - - public KVPairList getDefaultInstanceForType() { - return defaultInstance; - } - - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return com.alibaba.rocketmq.remoting.protocol.RemotingProtos.internal_static_remoting_KVPairList_descriptor; - } - - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return com.alibaba.rocketmq.remoting.protocol.RemotingProtos.internal_static_remoting_KVPairList_fieldAccessorTable; - } - - // repeated .remoting.KVPair fields = 1; - public static final int FIELDS_FIELD_NUMBER = 1; - private java.util.List fields_; - public java.util.List getFieldsList() { - return fields_; - } - public java.util.List - getFieldsOrBuilderList() { - return fields_; - } - public int getFieldsCount() { - return fields_.size(); - } - public com.alibaba.rocketmq.remoting.protocol.RemotingProtos.KVPair getFields(int index) { - return fields_.get(index); - } - public com.alibaba.rocketmq.remoting.protocol.RemotingProtos.KVPairOrBuilder getFieldsOrBuilder( - int index) { - return fields_.get(index); - } - - private void initFields() { - fields_ = java.util.Collections.emptyList(); - } - private byte memoizedIsInitialized = -1; - public final boolean isInitialized() { - byte isInitialized = memoizedIsInitialized; - if (isInitialized != -1) return isInitialized == 1; - - for (int i = 0; i < getFieldsCount(); i++) { - if (!getFields(i).isInitialized()) { - memoizedIsInitialized = 0; - return false; - } - } - memoizedIsInitialized = 1; - return true; - } - - public void writeTo(com.google.protobuf.CodedOutputStream output) - throws java.io.IOException { - getSerializedSize(); - for (int i = 0; i < fields_.size(); i++) { - output.writeMessage(1, fields_.get(i)); - } - getUnknownFields().writeTo(output); - } - - private int memoizedSerializedSize = -1; - public int getSerializedSize() { - int size = memoizedSerializedSize; - if (size != -1) return size; - - size = 0; - for (int i = 0; i < fields_.size(); i++) { - size += com.google.protobuf.CodedOutputStream - .computeMessageSize(1, fields_.get(i)); - } - size += getUnknownFields().getSerializedSize(); - memoizedSerializedSize = size; - return size; - } - - private static final long serialVersionUID = 0L; - @java.lang.Override - protected java.lang.Object writeReplace() - throws java.io.ObjectStreamException { - return super.writeReplace(); - } - - public static com.alibaba.rocketmq.remoting.protocol.RemotingProtos.KVPairList parseFrom( - com.google.protobuf.ByteString data) - throws com.google.protobuf.InvalidProtocolBufferException { - return newBuilder().mergeFrom(data).buildParsed(); - } - public static com.alibaba.rocketmq.remoting.protocol.RemotingProtos.KVPairList parseFrom( - com.google.protobuf.ByteString data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return newBuilder().mergeFrom(data, extensionRegistry) - .buildParsed(); - } - public static com.alibaba.rocketmq.remoting.protocol.RemotingProtos.KVPairList parseFrom(byte[] data) - throws com.google.protobuf.InvalidProtocolBufferException { - return newBuilder().mergeFrom(data).buildParsed(); - } - public static com.alibaba.rocketmq.remoting.protocol.RemotingProtos.KVPairList parseFrom( - byte[] data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return newBuilder().mergeFrom(data, extensionRegistry) - .buildParsed(); - } - public static com.alibaba.rocketmq.remoting.protocol.RemotingProtos.KVPairList parseFrom(java.io.InputStream input) - throws java.io.IOException { - return newBuilder().mergeFrom(input).buildParsed(); - } - public static com.alibaba.rocketmq.remoting.protocol.RemotingProtos.KVPairList parseFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return newBuilder().mergeFrom(input, extensionRegistry) - .buildParsed(); - } - public static com.alibaba.rocketmq.remoting.protocol.RemotingProtos.KVPairList parseDelimitedFrom(java.io.InputStream input) - throws java.io.IOException { - Builder builder = newBuilder(); - if (builder.mergeDelimitedFrom(input)) { - return builder.buildParsed(); - } else { - return null; - } - } - public static com.alibaba.rocketmq.remoting.protocol.RemotingProtos.KVPairList parseDelimitedFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - Builder builder = newBuilder(); - if (builder.mergeDelimitedFrom(input, extensionRegistry)) { - return builder.buildParsed(); - } else { - return null; - } - } - public static com.alibaba.rocketmq.remoting.protocol.RemotingProtos.KVPairList parseFrom( - com.google.protobuf.CodedInputStream input) - throws java.io.IOException { - return newBuilder().mergeFrom(input).buildParsed(); - } - public static com.alibaba.rocketmq.remoting.protocol.RemotingProtos.KVPairList parseFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return newBuilder().mergeFrom(input, extensionRegistry) - .buildParsed(); - } - - public static Builder newBuilder() { return Builder.create(); } - public Builder newBuilderForType() { return newBuilder(); } - public static Builder newBuilder(com.alibaba.rocketmq.remoting.protocol.RemotingProtos.KVPairList prototype) { - return newBuilder().mergeFrom(prototype); - } - public Builder toBuilder() { return newBuilder(this); } - - @java.lang.Override - protected Builder newBuilderForType( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - Builder builder = new Builder(parent); - return builder; - } - public static final class Builder extends - com.google.protobuf.GeneratedMessage.Builder - implements com.alibaba.rocketmq.remoting.protocol.RemotingProtos.KVPairListOrBuilder { - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return com.alibaba.rocketmq.remoting.protocol.RemotingProtos.internal_static_remoting_KVPairList_descriptor; - } - - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return com.alibaba.rocketmq.remoting.protocol.RemotingProtos.internal_static_remoting_KVPairList_fieldAccessorTable; - } - - // Construct using com.alibaba.rocketmq.remoting.protocol.RemotingProtos.KVPairList.newBuilder() - private Builder() { - maybeForceBuilderInitialization(); - } - - private Builder(BuilderParent parent) { - super(parent); - maybeForceBuilderInitialization(); - } - private void maybeForceBuilderInitialization() { - if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) { - getFieldsFieldBuilder(); - } - } - private static Builder create() { - return new Builder(); - } - - public Builder clear() { - super.clear(); - if (fieldsBuilder_ == null) { - fields_ = java.util.Collections.emptyList(); - bitField0_ = (bitField0_ & ~0x00000001); - } else { - fieldsBuilder_.clear(); - } - return this; - } - - public Builder clone() { - return create().mergeFrom(buildPartial()); - } - - public com.google.protobuf.Descriptors.Descriptor - getDescriptorForType() { - return com.alibaba.rocketmq.remoting.protocol.RemotingProtos.KVPairList.getDescriptor(); - } - - public com.alibaba.rocketmq.remoting.protocol.RemotingProtos.KVPairList getDefaultInstanceForType() { - return com.alibaba.rocketmq.remoting.protocol.RemotingProtos.KVPairList.getDefaultInstance(); - } - - public com.alibaba.rocketmq.remoting.protocol.RemotingProtos.KVPairList build() { - com.alibaba.rocketmq.remoting.protocol.RemotingProtos.KVPairList result = buildPartial(); - if (!result.isInitialized()) { - throw newUninitializedMessageException(result); - } - return result; - } - - private com.alibaba.rocketmq.remoting.protocol.RemotingProtos.KVPairList buildParsed() - throws com.google.protobuf.InvalidProtocolBufferException { - com.alibaba.rocketmq.remoting.protocol.RemotingProtos.KVPairList result = buildPartial(); - if (!result.isInitialized()) { - throw newUninitializedMessageException( - result).asInvalidProtocolBufferException(); - } - return result; - } - - public com.alibaba.rocketmq.remoting.protocol.RemotingProtos.KVPairList buildPartial() { - com.alibaba.rocketmq.remoting.protocol.RemotingProtos.KVPairList result = new com.alibaba.rocketmq.remoting.protocol.RemotingProtos.KVPairList(this); - int from_bitField0_ = bitField0_; - if (fieldsBuilder_ == null) { - if (((bitField0_ & 0x00000001) == 0x00000001)) { - fields_ = java.util.Collections.unmodifiableList(fields_); - bitField0_ = (bitField0_ & ~0x00000001); - } - result.fields_ = fields_; - } else { - result.fields_ = fieldsBuilder_.build(); - } - onBuilt(); - return result; - } - - public Builder mergeFrom(com.google.protobuf.Message other) { - if (other instanceof com.alibaba.rocketmq.remoting.protocol.RemotingProtos.KVPairList) { - return mergeFrom((com.alibaba.rocketmq.remoting.protocol.RemotingProtos.KVPairList)other); - } else { - super.mergeFrom(other); - return this; - } - } - - public Builder mergeFrom(com.alibaba.rocketmq.remoting.protocol.RemotingProtos.KVPairList other) { - if (other == com.alibaba.rocketmq.remoting.protocol.RemotingProtos.KVPairList.getDefaultInstance()) return this; - if (fieldsBuilder_ == null) { - if (!other.fields_.isEmpty()) { - if (fields_.isEmpty()) { - fields_ = other.fields_; - bitField0_ = (bitField0_ & ~0x00000001); - } else { - ensureFieldsIsMutable(); - fields_.addAll(other.fields_); - } - onChanged(); - } - } else { - if (!other.fields_.isEmpty()) { - if (fieldsBuilder_.isEmpty()) { - fieldsBuilder_.dispose(); - fieldsBuilder_ = null; - fields_ = other.fields_; - bitField0_ = (bitField0_ & ~0x00000001); - fieldsBuilder_ = - com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders ? - getFieldsFieldBuilder() : null; - } else { - fieldsBuilder_.addAllMessages(other.fields_); - } - } - } - this.mergeUnknownFields(other.getUnknownFields()); - return this; - } - - public final boolean isInitialized() { - for (int i = 0; i < getFieldsCount(); i++) { - if (!getFields(i).isInitialized()) { - - return false; - } - } - return true; - } - - public Builder mergeFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - com.google.protobuf.UnknownFieldSet.Builder unknownFields = - com.google.protobuf.UnknownFieldSet.newBuilder( - this.getUnknownFields()); - while (true) { - int tag = input.readTag(); - switch (tag) { - case 0: - this.setUnknownFields(unknownFields.build()); - onChanged(); - return this; - default: { - if (!parseUnknownField(input, unknownFields, - extensionRegistry, tag)) { - this.setUnknownFields(unknownFields.build()); - onChanged(); - return this; - } - break; - } - case 10: { - com.alibaba.rocketmq.remoting.protocol.RemotingProtos.KVPair.Builder subBuilder = com.alibaba.rocketmq.remoting.protocol.RemotingProtos.KVPair.newBuilder(); - input.readMessage(subBuilder, extensionRegistry); - addFields(subBuilder.buildPartial()); - break; - } - } - } - } - - private int bitField0_; - - // repeated .remoting.KVPair fields = 1; - private java.util.List fields_ = - java.util.Collections.emptyList(); - private void ensureFieldsIsMutable() { - if (!((bitField0_ & 0x00000001) == 0x00000001)) { - fields_ = new java.util.ArrayList(fields_); - bitField0_ |= 0x00000001; - } - } - - private com.google.protobuf.RepeatedFieldBuilder< - com.alibaba.rocketmq.remoting.protocol.RemotingProtos.KVPair, com.alibaba.rocketmq.remoting.protocol.RemotingProtos.KVPair.Builder, com.alibaba.rocketmq.remoting.protocol.RemotingProtos.KVPairOrBuilder> fieldsBuilder_; - - public java.util.List getFieldsList() { - if (fieldsBuilder_ == null) { - return java.util.Collections.unmodifiableList(fields_); - } else { - return fieldsBuilder_.getMessageList(); - } - } - public int getFieldsCount() { - if (fieldsBuilder_ == null) { - return fields_.size(); - } else { - return fieldsBuilder_.getCount(); - } - } - public com.alibaba.rocketmq.remoting.protocol.RemotingProtos.KVPair getFields(int index) { - if (fieldsBuilder_ == null) { - return fields_.get(index); - } else { - return fieldsBuilder_.getMessage(index); - } - } - public Builder setFields( - int index, com.alibaba.rocketmq.remoting.protocol.RemotingProtos.KVPair value) { - if (fieldsBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - ensureFieldsIsMutable(); - fields_.set(index, value); - onChanged(); - } else { - fieldsBuilder_.setMessage(index, value); - } - return this; - } - public Builder setFields( - int index, com.alibaba.rocketmq.remoting.protocol.RemotingProtos.KVPair.Builder builderForValue) { - if (fieldsBuilder_ == null) { - ensureFieldsIsMutable(); - fields_.set(index, builderForValue.build()); - onChanged(); - } else { - fieldsBuilder_.setMessage(index, builderForValue.build()); - } - return this; - } - public Builder addFields(com.alibaba.rocketmq.remoting.protocol.RemotingProtos.KVPair value) { - if (fieldsBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - ensureFieldsIsMutable(); - fields_.add(value); - onChanged(); - } else { - fieldsBuilder_.addMessage(value); - } - return this; - } - public Builder addFields( - int index, com.alibaba.rocketmq.remoting.protocol.RemotingProtos.KVPair value) { - if (fieldsBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - ensureFieldsIsMutable(); - fields_.add(index, value); - onChanged(); - } else { - fieldsBuilder_.addMessage(index, value); - } - return this; - } - public Builder addFields( - com.alibaba.rocketmq.remoting.protocol.RemotingProtos.KVPair.Builder builderForValue) { - if (fieldsBuilder_ == null) { - ensureFieldsIsMutable(); - fields_.add(builderForValue.build()); - onChanged(); - } else { - fieldsBuilder_.addMessage(builderForValue.build()); - } - return this; - } - public Builder addFields( - int index, com.alibaba.rocketmq.remoting.protocol.RemotingProtos.KVPair.Builder builderForValue) { - if (fieldsBuilder_ == null) { - ensureFieldsIsMutable(); - fields_.add(index, builderForValue.build()); - onChanged(); - } else { - fieldsBuilder_.addMessage(index, builderForValue.build()); - } - return this; - } - public Builder addAllFields( - java.lang.Iterable values) { - if (fieldsBuilder_ == null) { - ensureFieldsIsMutable(); - super.addAll(values, fields_); - onChanged(); - } else { - fieldsBuilder_.addAllMessages(values); - } - return this; - } - public Builder clearFields() { - if (fieldsBuilder_ == null) { - fields_ = java.util.Collections.emptyList(); - bitField0_ = (bitField0_ & ~0x00000001); - onChanged(); - } else { - fieldsBuilder_.clear(); - } - return this; - } - public Builder removeFields(int index) { - if (fieldsBuilder_ == null) { - ensureFieldsIsMutable(); - fields_.remove(index); - onChanged(); - } else { - fieldsBuilder_.remove(index); - } - return this; - } - public com.alibaba.rocketmq.remoting.protocol.RemotingProtos.KVPair.Builder getFieldsBuilder( - int index) { - return getFieldsFieldBuilder().getBuilder(index); - } - public com.alibaba.rocketmq.remoting.protocol.RemotingProtos.KVPairOrBuilder getFieldsOrBuilder( - int index) { - if (fieldsBuilder_ == null) { - return fields_.get(index); } else { - return fieldsBuilder_.getMessageOrBuilder(index); - } - } - public java.util.List - getFieldsOrBuilderList() { - if (fieldsBuilder_ != null) { - return fieldsBuilder_.getMessageOrBuilderList(); - } else { - return java.util.Collections.unmodifiableList(fields_); - } - } - public com.alibaba.rocketmq.remoting.protocol.RemotingProtos.KVPair.Builder addFieldsBuilder() { - return getFieldsFieldBuilder().addBuilder( - com.alibaba.rocketmq.remoting.protocol.RemotingProtos.KVPair.getDefaultInstance()); - } - public com.alibaba.rocketmq.remoting.protocol.RemotingProtos.KVPair.Builder addFieldsBuilder( - int index) { - return getFieldsFieldBuilder().addBuilder( - index, com.alibaba.rocketmq.remoting.protocol.RemotingProtos.KVPair.getDefaultInstance()); - } - public java.util.List - getFieldsBuilderList() { - return getFieldsFieldBuilder().getBuilderList(); - } - private com.google.protobuf.RepeatedFieldBuilder< - com.alibaba.rocketmq.remoting.protocol.RemotingProtos.KVPair, com.alibaba.rocketmq.remoting.protocol.RemotingProtos.KVPair.Builder, com.alibaba.rocketmq.remoting.protocol.RemotingProtos.KVPairOrBuilder> - getFieldsFieldBuilder() { - if (fieldsBuilder_ == null) { - fieldsBuilder_ = new com.google.protobuf.RepeatedFieldBuilder< - com.alibaba.rocketmq.remoting.protocol.RemotingProtos.KVPair, com.alibaba.rocketmq.remoting.protocol.RemotingProtos.KVPair.Builder, com.alibaba.rocketmq.remoting.protocol.RemotingProtos.KVPairOrBuilder>( - fields_, - ((bitField0_ & 0x00000001) == 0x00000001), - getParentForChildren(), - isClean()); - fields_ = null; - } - return fieldsBuilder_; - } - - // @@protoc_insertion_point(builder_scope:remoting.KVPairList) - } - - static { - defaultInstance = new KVPairList(true); - defaultInstance.initFields(); - } - - // @@protoc_insertion_point(class_scope:remoting.KVPairList) - } - - public interface NVPairOrBuilder - extends com.google.protobuf.MessageOrBuilder { - - // required string name = 1; - boolean hasName(); - String getName(); - - // required string value = 2; - boolean hasValue(); - String getValue(); - } - public static final class NVPair extends - com.google.protobuf.GeneratedMessage - implements NVPairOrBuilder { - // Use NVPair.newBuilder() to construct. - private NVPair(Builder builder) { - super(builder); - } - private NVPair(boolean noInit) {} - - private static final NVPair defaultInstance; - public static NVPair getDefaultInstance() { - return defaultInstance; - } - - public NVPair getDefaultInstanceForType() { - return defaultInstance; - } - - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return com.alibaba.rocketmq.remoting.protocol.RemotingProtos.internal_static_remoting_NVPair_descriptor; - } - - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return com.alibaba.rocketmq.remoting.protocol.RemotingProtos.internal_static_remoting_NVPair_fieldAccessorTable; - } - - private int bitField0_; - // required string name = 1; - public static final int NAME_FIELD_NUMBER = 1; - private java.lang.Object name_; - public boolean hasName() { - return ((bitField0_ & 0x00000001) == 0x00000001); - } - public String getName() { - java.lang.Object ref = name_; - if (ref instanceof String) { - return (String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - String s = bs.toStringUtf8(); - if (com.google.protobuf.Internal.isValidUtf8(bs)) { - name_ = s; - } - return s; - } - } - private com.google.protobuf.ByteString getNameBytes() { - java.lang.Object ref = name_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8((String) ref); - name_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - // required string value = 2; - public static final int VALUE_FIELD_NUMBER = 2; - private java.lang.Object value_; - public boolean hasValue() { - return ((bitField0_ & 0x00000002) == 0x00000002); - } - public String getValue() { - java.lang.Object ref = value_; - if (ref instanceof String) { - return (String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - String s = bs.toStringUtf8(); - if (com.google.protobuf.Internal.isValidUtf8(bs)) { - value_ = s; - } - return s; - } - } - private com.google.protobuf.ByteString getValueBytes() { - java.lang.Object ref = value_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8((String) ref); - value_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - private void initFields() { - name_ = ""; - value_ = ""; - } - private byte memoizedIsInitialized = -1; - public final boolean isInitialized() { - byte isInitialized = memoizedIsInitialized; - if (isInitialized != -1) return isInitialized == 1; - - if (!hasName()) { - memoizedIsInitialized = 0; - return false; - } - if (!hasValue()) { - memoizedIsInitialized = 0; - return false; - } - memoizedIsInitialized = 1; - return true; - } - - public void writeTo(com.google.protobuf.CodedOutputStream output) - throws java.io.IOException { - getSerializedSize(); - if (((bitField0_ & 0x00000001) == 0x00000001)) { - output.writeBytes(1, getNameBytes()); - } - if (((bitField0_ & 0x00000002) == 0x00000002)) { - output.writeBytes(2, getValueBytes()); - } - getUnknownFields().writeTo(output); - } - - private int memoizedSerializedSize = -1; - public int getSerializedSize() { - int size = memoizedSerializedSize; - if (size != -1) return size; - - size = 0; - if (((bitField0_ & 0x00000001) == 0x00000001)) { - size += com.google.protobuf.CodedOutputStream - .computeBytesSize(1, getNameBytes()); - } - if (((bitField0_ & 0x00000002) == 0x00000002)) { - size += com.google.protobuf.CodedOutputStream - .computeBytesSize(2, getValueBytes()); - } - size += getUnknownFields().getSerializedSize(); - memoizedSerializedSize = size; - return size; - } - - private static final long serialVersionUID = 0L; - @java.lang.Override - protected java.lang.Object writeReplace() - throws java.io.ObjectStreamException { - return super.writeReplace(); - } - - public static com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPair parseFrom( - com.google.protobuf.ByteString data) - throws com.google.protobuf.InvalidProtocolBufferException { - return newBuilder().mergeFrom(data).buildParsed(); - } - public static com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPair parseFrom( - com.google.protobuf.ByteString data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return newBuilder().mergeFrom(data, extensionRegistry) - .buildParsed(); - } - public static com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPair parseFrom(byte[] data) - throws com.google.protobuf.InvalidProtocolBufferException { - return newBuilder().mergeFrom(data).buildParsed(); - } - public static com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPair parseFrom( - byte[] data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return newBuilder().mergeFrom(data, extensionRegistry) - .buildParsed(); - } - public static com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPair parseFrom(java.io.InputStream input) - throws java.io.IOException { - return newBuilder().mergeFrom(input).buildParsed(); - } - public static com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPair parseFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return newBuilder().mergeFrom(input, extensionRegistry) - .buildParsed(); - } - public static com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPair parseDelimitedFrom(java.io.InputStream input) - throws java.io.IOException { - Builder builder = newBuilder(); - if (builder.mergeDelimitedFrom(input)) { - return builder.buildParsed(); - } else { - return null; - } - } - public static com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPair parseDelimitedFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - Builder builder = newBuilder(); - if (builder.mergeDelimitedFrom(input, extensionRegistry)) { - return builder.buildParsed(); - } else { - return null; - } - } - public static com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPair parseFrom( - com.google.protobuf.CodedInputStream input) - throws java.io.IOException { - return newBuilder().mergeFrom(input).buildParsed(); - } - public static com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPair parseFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return newBuilder().mergeFrom(input, extensionRegistry) - .buildParsed(); - } - - public static Builder newBuilder() { return Builder.create(); } - public Builder newBuilderForType() { return newBuilder(); } - public static Builder newBuilder(com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPair prototype) { - return newBuilder().mergeFrom(prototype); - } - public Builder toBuilder() { return newBuilder(this); } - - @java.lang.Override - protected Builder newBuilderForType( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - Builder builder = new Builder(parent); - return builder; - } - public static final class Builder extends - com.google.protobuf.GeneratedMessage.Builder - implements com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPairOrBuilder { - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return com.alibaba.rocketmq.remoting.protocol.RemotingProtos.internal_static_remoting_NVPair_descriptor; - } - - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return com.alibaba.rocketmq.remoting.protocol.RemotingProtos.internal_static_remoting_NVPair_fieldAccessorTable; - } - - // Construct using com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPair.newBuilder() - private Builder() { - maybeForceBuilderInitialization(); - } - - private Builder(BuilderParent parent) { - super(parent); - maybeForceBuilderInitialization(); - } - private void maybeForceBuilderInitialization() { - if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) { - } - } - private static Builder create() { - return new Builder(); - } - - public Builder clear() { - super.clear(); - name_ = ""; - bitField0_ = (bitField0_ & ~0x00000001); - value_ = ""; - bitField0_ = (bitField0_ & ~0x00000002); - return this; - } - - public Builder clone() { - return create().mergeFrom(buildPartial()); - } - - public com.google.protobuf.Descriptors.Descriptor - getDescriptorForType() { - return com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPair.getDescriptor(); - } - - public com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPair getDefaultInstanceForType() { - return com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPair.getDefaultInstance(); - } - - public com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPair build() { - com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPair result = buildPartial(); - if (!result.isInitialized()) { - throw newUninitializedMessageException(result); - } - return result; - } - - private com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPair buildParsed() - throws com.google.protobuf.InvalidProtocolBufferException { - com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPair result = buildPartial(); - if (!result.isInitialized()) { - throw newUninitializedMessageException( - result).asInvalidProtocolBufferException(); - } - return result; - } - - public com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPair buildPartial() { - com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPair result = new com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPair(this); - int from_bitField0_ = bitField0_; - int to_bitField0_ = 0; - if (((from_bitField0_ & 0x00000001) == 0x00000001)) { - to_bitField0_ |= 0x00000001; - } - result.name_ = name_; - if (((from_bitField0_ & 0x00000002) == 0x00000002)) { - to_bitField0_ |= 0x00000002; - } - result.value_ = value_; - result.bitField0_ = to_bitField0_; - onBuilt(); - return result; - } - - public Builder mergeFrom(com.google.protobuf.Message other) { - if (other instanceof com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPair) { - return mergeFrom((com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPair)other); - } else { - super.mergeFrom(other); - return this; - } - } - - public Builder mergeFrom(com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPair other) { - if (other == com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPair.getDefaultInstance()) return this; - if (other.hasName()) { - setName(other.getName()); - } - if (other.hasValue()) { - setValue(other.getValue()); - } - this.mergeUnknownFields(other.getUnknownFields()); - return this; - } - - public final boolean isInitialized() { - if (!hasName()) { - - return false; - } - if (!hasValue()) { - - return false; - } - return true; - } - - public Builder mergeFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - com.google.protobuf.UnknownFieldSet.Builder unknownFields = - com.google.protobuf.UnknownFieldSet.newBuilder( - this.getUnknownFields()); - while (true) { - int tag = input.readTag(); - switch (tag) { - case 0: - this.setUnknownFields(unknownFields.build()); - onChanged(); - return this; - default: { - if (!parseUnknownField(input, unknownFields, - extensionRegistry, tag)) { - this.setUnknownFields(unknownFields.build()); - onChanged(); - return this; - } - break; - } - case 10: { - bitField0_ |= 0x00000001; - name_ = input.readBytes(); - break; - } - case 18: { - bitField0_ |= 0x00000002; - value_ = input.readBytes(); - break; - } - } - } - } - - private int bitField0_; - - // required string name = 1; - private java.lang.Object name_ = ""; - public boolean hasName() { - return ((bitField0_ & 0x00000001) == 0x00000001); - } - public String getName() { - java.lang.Object ref = name_; - if (!(ref instanceof String)) { - String s = ((com.google.protobuf.ByteString) ref).toStringUtf8(); - name_ = s; - return s; - } else { - return (String) ref; - } - } - public Builder setName(String value) { - if (value == null) { - throw new NullPointerException(); - } - bitField0_ |= 0x00000001; - name_ = value; - onChanged(); - return this; - } - public Builder clearName() { - bitField0_ = (bitField0_ & ~0x00000001); - name_ = getDefaultInstance().getName(); - onChanged(); - return this; - } - void setName(com.google.protobuf.ByteString value) { - bitField0_ |= 0x00000001; - name_ = value; - onChanged(); - } - - // required string value = 2; - private java.lang.Object value_ = ""; - public boolean hasValue() { - return ((bitField0_ & 0x00000002) == 0x00000002); - } - public String getValue() { - java.lang.Object ref = value_; - if (!(ref instanceof String)) { - String s = ((com.google.protobuf.ByteString) ref).toStringUtf8(); - value_ = s; - return s; - } else { - return (String) ref; - } - } - public Builder setValue(String value) { - if (value == null) { - throw new NullPointerException(); - } - bitField0_ |= 0x00000002; - value_ = value; - onChanged(); - return this; - } - public Builder clearValue() { - bitField0_ = (bitField0_ & ~0x00000002); - value_ = getDefaultInstance().getValue(); - onChanged(); - return this; - } - void setValue(com.google.protobuf.ByteString value) { - bitField0_ |= 0x00000002; - value_ = value; - onChanged(); - } - - // @@protoc_insertion_point(builder_scope:remoting.NVPair) - } - - static { - defaultInstance = new NVPair(true); - defaultInstance.initFields(); - } - - // @@protoc_insertion_point(class_scope:remoting.NVPair) - } - - public interface NVPairListOrBuilder - extends com.google.protobuf.MessageOrBuilder { - - // repeated .remoting.NVPair fields = 1; - java.util.List - getFieldsList(); - com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPair getFields(int index); - int getFieldsCount(); - java.util.List - getFieldsOrBuilderList(); - com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPairOrBuilder getFieldsOrBuilder( - int index); - } - public static final class NVPairList extends - com.google.protobuf.GeneratedMessage - implements NVPairListOrBuilder { - // Use NVPairList.newBuilder() to construct. - private NVPairList(Builder builder) { - super(builder); - } - private NVPairList(boolean noInit) {} - - private static final NVPairList defaultInstance; - public static NVPairList getDefaultInstance() { - return defaultInstance; - } - - public NVPairList getDefaultInstanceForType() { - return defaultInstance; - } - - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return com.alibaba.rocketmq.remoting.protocol.RemotingProtos.internal_static_remoting_NVPairList_descriptor; - } - - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return com.alibaba.rocketmq.remoting.protocol.RemotingProtos.internal_static_remoting_NVPairList_fieldAccessorTable; - } - - // repeated .remoting.NVPair fields = 1; - public static final int FIELDS_FIELD_NUMBER = 1; - private java.util.List fields_; - public java.util.List getFieldsList() { - return fields_; - } - public java.util.List - getFieldsOrBuilderList() { - return fields_; - } - public int getFieldsCount() { - return fields_.size(); + private RemotingProtos() { } - public com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPair getFields(int index) { - return fields_.get(index); - } - public com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPairOrBuilder getFieldsOrBuilder( - int index) { - return fields_.get(index); - } - - private void initFields() { - fields_ = java.util.Collections.emptyList(); - } - private byte memoizedIsInitialized = -1; - public final boolean isInitialized() { - byte isInitialized = memoizedIsInitialized; - if (isInitialized != -1) return isInitialized == 1; - - for (int i = 0; i < getFieldsCount(); i++) { - if (!getFields(i).isInitialized()) { - memoizedIsInitialized = 0; - return false; - } - } - memoizedIsInitialized = 1; - return true; - } - - public void writeTo(com.google.protobuf.CodedOutputStream output) - throws java.io.IOException { - getSerializedSize(); - for (int i = 0; i < fields_.size(); i++) { - output.writeMessage(1, fields_.get(i)); - } - getUnknownFields().writeTo(output); - } - - private int memoizedSerializedSize = -1; - public int getSerializedSize() { - int size = memoizedSerializedSize; - if (size != -1) return size; - - size = 0; - for (int i = 0; i < fields_.size(); i++) { - size += com.google.protobuf.CodedOutputStream - .computeMessageSize(1, fields_.get(i)); - } - size += getUnknownFields().getSerializedSize(); - memoizedSerializedSize = size; - return size; - } - - private static final long serialVersionUID = 0L; - @java.lang.Override - protected java.lang.Object writeReplace() - throws java.io.ObjectStreamException { - return super.writeReplace(); - } - - public static com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPairList parseFrom( - com.google.protobuf.ByteString data) - throws com.google.protobuf.InvalidProtocolBufferException { - return newBuilder().mergeFrom(data).buildParsed(); - } - public static com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPairList parseFrom( - com.google.protobuf.ByteString data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return newBuilder().mergeFrom(data, extensionRegistry) - .buildParsed(); - } - public static com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPairList parseFrom(byte[] data) - throws com.google.protobuf.InvalidProtocolBufferException { - return newBuilder().mergeFrom(data).buildParsed(); - } - public static com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPairList parseFrom( - byte[] data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return newBuilder().mergeFrom(data, extensionRegistry) - .buildParsed(); - } - public static com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPairList parseFrom(java.io.InputStream input) - throws java.io.IOException { - return newBuilder().mergeFrom(input).buildParsed(); - } - public static com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPairList parseFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return newBuilder().mergeFrom(input, extensionRegistry) - .buildParsed(); - } - public static com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPairList parseDelimitedFrom(java.io.InputStream input) - throws java.io.IOException { - Builder builder = newBuilder(); - if (builder.mergeDelimitedFrom(input)) { - return builder.buildParsed(); - } else { - return null; - } - } - public static com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPairList parseDelimitedFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - Builder builder = newBuilder(); - if (builder.mergeDelimitedFrom(input, extensionRegistry)) { - return builder.buildParsed(); - } else { - return null; - } - } - public static com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPairList parseFrom( - com.google.protobuf.CodedInputStream input) - throws java.io.IOException { - return newBuilder().mergeFrom(input).buildParsed(); - } - public static com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPairList parseFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return newBuilder().mergeFrom(input, extensionRegistry) - .buildParsed(); - } - - public static Builder newBuilder() { return Builder.create(); } - public Builder newBuilderForType() { return newBuilder(); } - public static Builder newBuilder(com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPairList prototype) { - return newBuilder().mergeFrom(prototype); - } - public Builder toBuilder() { return newBuilder(this); } - - @java.lang.Override - protected Builder newBuilderForType( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - Builder builder = new Builder(parent); - return builder; - } - public static final class Builder extends - com.google.protobuf.GeneratedMessage.Builder - implements com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPairListOrBuilder { - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return com.alibaba.rocketmq.remoting.protocol.RemotingProtos.internal_static_remoting_NVPairList_descriptor; - } - - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return com.alibaba.rocketmq.remoting.protocol.RemotingProtos.internal_static_remoting_NVPairList_fieldAccessorTable; - } - - // Construct using com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPairList.newBuilder() - private Builder() { - maybeForceBuilderInitialization(); - } - - private Builder(BuilderParent parent) { - super(parent); - maybeForceBuilderInitialization(); - } - private void maybeForceBuilderInitialization() { - if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) { - getFieldsFieldBuilder(); - } - } - private static Builder create() { - return new Builder(); - } - - public Builder clear() { - super.clear(); - if (fieldsBuilder_ == null) { - fields_ = java.util.Collections.emptyList(); - bitField0_ = (bitField0_ & ~0x00000001); - } else { - fieldsBuilder_.clear(); - } - return this; - } - - public Builder clone() { - return create().mergeFrom(buildPartial()); - } - - public com.google.protobuf.Descriptors.Descriptor - getDescriptorForType() { - return com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPairList.getDescriptor(); - } - - public com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPairList getDefaultInstanceForType() { - return com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPairList.getDefaultInstance(); - } - - public com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPairList build() { - com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPairList result = buildPartial(); - if (!result.isInitialized()) { - throw newUninitializedMessageException(result); - } - return result; - } - - private com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPairList buildParsed() - throws com.google.protobuf.InvalidProtocolBufferException { - com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPairList result = buildPartial(); - if (!result.isInitialized()) { - throw newUninitializedMessageException( - result).asInvalidProtocolBufferException(); - } - return result; - } - - public com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPairList buildPartial() { - com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPairList result = new com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPairList(this); - int from_bitField0_ = bitField0_; - if (fieldsBuilder_ == null) { - if (((bitField0_ & 0x00000001) == 0x00000001)) { - fields_ = java.util.Collections.unmodifiableList(fields_); - bitField0_ = (bitField0_ & ~0x00000001); - } - result.fields_ = fields_; - } else { - result.fields_ = fieldsBuilder_.build(); - } - onBuilt(); - return result; - } - - public Builder mergeFrom(com.google.protobuf.Message other) { - if (other instanceof com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPairList) { - return mergeFrom((com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPairList)other); - } else { - super.mergeFrom(other); - return this; - } - } - - public Builder mergeFrom(com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPairList other) { - if (other == com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPairList.getDefaultInstance()) return this; - if (fieldsBuilder_ == null) { - if (!other.fields_.isEmpty()) { - if (fields_.isEmpty()) { - fields_ = other.fields_; - bitField0_ = (bitField0_ & ~0x00000001); - } else { - ensureFieldsIsMutable(); - fields_.addAll(other.fields_); - } - onChanged(); - } - } else { - if (!other.fields_.isEmpty()) { - if (fieldsBuilder_.isEmpty()) { - fieldsBuilder_.dispose(); - fieldsBuilder_ = null; - fields_ = other.fields_; - bitField0_ = (bitField0_ & ~0x00000001); - fieldsBuilder_ = - com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders ? - getFieldsFieldBuilder() : null; - } else { - fieldsBuilder_.addAllMessages(other.fields_); - } - } - } - this.mergeUnknownFields(other.getUnknownFields()); - return this; - } - - public final boolean isInitialized() { - for (int i = 0; i < getFieldsCount(); i++) { - if (!getFields(i).isInitialized()) { - - return false; - } - } - return true; - } - - public Builder mergeFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - com.google.protobuf.UnknownFieldSet.Builder unknownFields = - com.google.protobuf.UnknownFieldSet.newBuilder( - this.getUnknownFields()); - while (true) { - int tag = input.readTag(); - switch (tag) { - case 0: - this.setUnknownFields(unknownFields.build()); - onChanged(); - return this; - default: { - if (!parseUnknownField(input, unknownFields, - extensionRegistry, tag)) { - this.setUnknownFields(unknownFields.build()); - onChanged(); - return this; - } - break; - } - case 10: { - com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPair.Builder subBuilder = com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPair.newBuilder(); - input.readMessage(subBuilder, extensionRegistry); - addFields(subBuilder.buildPartial()); - break; - } - } - } - } - - private int bitField0_; - - // repeated .remoting.NVPair fields = 1; - private java.util.List fields_ = - java.util.Collections.emptyList(); - private void ensureFieldsIsMutable() { - if (!((bitField0_ & 0x00000001) == 0x00000001)) { - fields_ = new java.util.ArrayList(fields_); - bitField0_ |= 0x00000001; - } - } - - private com.google.protobuf.RepeatedFieldBuilder< - com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPair, com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPair.Builder, com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPairOrBuilder> fieldsBuilder_; - - public java.util.List getFieldsList() { - if (fieldsBuilder_ == null) { - return java.util.Collections.unmodifiableList(fields_); - } else { - return fieldsBuilder_.getMessageList(); - } - } - public int getFieldsCount() { - if (fieldsBuilder_ == null) { - return fields_.size(); - } else { - return fieldsBuilder_.getCount(); - } - } - public com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPair getFields(int index) { - if (fieldsBuilder_ == null) { - return fields_.get(index); - } else { - return fieldsBuilder_.getMessage(index); - } - } - public Builder setFields( - int index, com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPair value) { - if (fieldsBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - ensureFieldsIsMutable(); - fields_.set(index, value); - onChanged(); - } else { - fieldsBuilder_.setMessage(index, value); - } - return this; - } - public Builder setFields( - int index, com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPair.Builder builderForValue) { - if (fieldsBuilder_ == null) { - ensureFieldsIsMutable(); - fields_.set(index, builderForValue.build()); - onChanged(); - } else { - fieldsBuilder_.setMessage(index, builderForValue.build()); - } - return this; - } - public Builder addFields(com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPair value) { - if (fieldsBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - ensureFieldsIsMutable(); - fields_.add(value); - onChanged(); - } else { - fieldsBuilder_.addMessage(value); - } - return this; - } - public Builder addFields( - int index, com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPair value) { - if (fieldsBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - ensureFieldsIsMutable(); - fields_.add(index, value); - onChanged(); - } else { - fieldsBuilder_.addMessage(index, value); - } - return this; - } - public Builder addFields( - com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPair.Builder builderForValue) { - if (fieldsBuilder_ == null) { - ensureFieldsIsMutable(); - fields_.add(builderForValue.build()); - onChanged(); - } else { - fieldsBuilder_.addMessage(builderForValue.build()); - } - return this; - } - public Builder addFields( - int index, com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPair.Builder builderForValue) { - if (fieldsBuilder_ == null) { - ensureFieldsIsMutable(); - fields_.add(index, builderForValue.build()); - onChanged(); - } else { - fieldsBuilder_.addMessage(index, builderForValue.build()); - } - return this; - } - public Builder addAllFields( - java.lang.Iterable values) { - if (fieldsBuilder_ == null) { - ensureFieldsIsMutable(); - super.addAll(values, fields_); - onChanged(); - } else { - fieldsBuilder_.addAllMessages(values); - } - return this; - } - public Builder clearFields() { - if (fieldsBuilder_ == null) { - fields_ = java.util.Collections.emptyList(); - bitField0_ = (bitField0_ & ~0x00000001); - onChanged(); - } else { - fieldsBuilder_.clear(); - } - return this; - } - public Builder removeFields(int index) { - if (fieldsBuilder_ == null) { - ensureFieldsIsMutable(); - fields_.remove(index); - onChanged(); - } else { - fieldsBuilder_.remove(index); - } - return this; - } - public com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPair.Builder getFieldsBuilder( - int index) { - return getFieldsFieldBuilder().getBuilder(index); - } - public com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPairOrBuilder getFieldsOrBuilder( - int index) { - if (fieldsBuilder_ == null) { - return fields_.get(index); } else { - return fieldsBuilder_.getMessageOrBuilder(index); - } - } - public java.util.List - getFieldsOrBuilderList() { - if (fieldsBuilder_ != null) { - return fieldsBuilder_.getMessageOrBuilderList(); - } else { - return java.util.Collections.unmodifiableList(fields_); - } - } - public com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPair.Builder addFieldsBuilder() { - return getFieldsFieldBuilder().addBuilder( - com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPair.getDefaultInstance()); - } - public com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPair.Builder addFieldsBuilder( - int index) { - return getFieldsFieldBuilder().addBuilder( - index, com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPair.getDefaultInstance()); - } - public java.util.List - getFieldsBuilderList() { - return getFieldsFieldBuilder().getBuilderList(); - } - private com.google.protobuf.RepeatedFieldBuilder< - com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPair, com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPair.Builder, com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPairOrBuilder> - getFieldsFieldBuilder() { - if (fieldsBuilder_ == null) { - fieldsBuilder_ = new com.google.protobuf.RepeatedFieldBuilder< - com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPair, com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPair.Builder, com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPairOrBuilder>( - fields_, - ((bitField0_ & 0x00000001) == 0x00000001), - getParentForChildren(), - isClean()); - fields_ = null; - } - return fieldsBuilder_; - } - - // @@protoc_insertion_point(builder_scope:remoting.NVPairList) - } - - static { - defaultInstance = new NVPairList(true); - defaultInstance.initFields(); - } - - // @@protoc_insertion_point(class_scope:remoting.NVPairList) - } - - public interface StringListOrBuilder - extends com.google.protobuf.MessageOrBuilder { - - // repeated string name = 1; - java.util.List getNameList(); - int getNameCount(); - String getName(int index); - } - public static final class StringList extends - com.google.protobuf.GeneratedMessage - implements StringListOrBuilder { - // Use StringList.newBuilder() to construct. - private StringList(Builder builder) { - super(builder); - } - private StringList(boolean noInit) {} - - private static final StringList defaultInstance; - public static StringList getDefaultInstance() { - return defaultInstance; - } - - public StringList getDefaultInstanceForType() { - return defaultInstance; - } - - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return com.alibaba.rocketmq.remoting.protocol.RemotingProtos.internal_static_remoting_StringList_descriptor; - } - - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return com.alibaba.rocketmq.remoting.protocol.RemotingProtos.internal_static_remoting_StringList_fieldAccessorTable; - } - - // repeated string name = 1; - public static final int NAME_FIELD_NUMBER = 1; - private com.google.protobuf.LazyStringList name_; - public java.util.List - getNameList() { - return name_; - } - public int getNameCount() { - return name_.size(); - } - public String getName(int index) { - return name_.get(index); - } - - private void initFields() { - name_ = com.google.protobuf.LazyStringArrayList.EMPTY; - } - private byte memoizedIsInitialized = -1; - public final boolean isInitialized() { - byte isInitialized = memoizedIsInitialized; - if (isInitialized != -1) return isInitialized == 1; - - memoizedIsInitialized = 1; - return true; - } - - public void writeTo(com.google.protobuf.CodedOutputStream output) - throws java.io.IOException { - getSerializedSize(); - for (int i = 0; i < name_.size(); i++) { - output.writeBytes(1, name_.getByteString(i)); - } - getUnknownFields().writeTo(output); - } - - private int memoizedSerializedSize = -1; - public int getSerializedSize() { - int size = memoizedSerializedSize; - if (size != -1) return size; - - size = 0; - { - int dataSize = 0; - for (int i = 0; i < name_.size(); i++) { - dataSize += com.google.protobuf.CodedOutputStream - .computeBytesSizeNoTag(name_.getByteString(i)); - } - size += dataSize; - size += 1 * getNameList().size(); - } - size += getUnknownFields().getSerializedSize(); - memoizedSerializedSize = size; - return size; - } - - private static final long serialVersionUID = 0L; - @java.lang.Override - protected java.lang.Object writeReplace() - throws java.io.ObjectStreamException { - return super.writeReplace(); - } - - public static com.alibaba.rocketmq.remoting.protocol.RemotingProtos.StringList parseFrom( - com.google.protobuf.ByteString data) - throws com.google.protobuf.InvalidProtocolBufferException { - return newBuilder().mergeFrom(data).buildParsed(); - } - public static com.alibaba.rocketmq.remoting.protocol.RemotingProtos.StringList parseFrom( - com.google.protobuf.ByteString data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return newBuilder().mergeFrom(data, extensionRegistry) - .buildParsed(); - } - public static com.alibaba.rocketmq.remoting.protocol.RemotingProtos.StringList parseFrom(byte[] data) - throws com.google.protobuf.InvalidProtocolBufferException { - return newBuilder().mergeFrom(data).buildParsed(); - } - public static com.alibaba.rocketmq.remoting.protocol.RemotingProtos.StringList parseFrom( - byte[] data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return newBuilder().mergeFrom(data, extensionRegistry) - .buildParsed(); - } - public static com.alibaba.rocketmq.remoting.protocol.RemotingProtos.StringList parseFrom(java.io.InputStream input) - throws java.io.IOException { - return newBuilder().mergeFrom(input).buildParsed(); - } - public static com.alibaba.rocketmq.remoting.protocol.RemotingProtos.StringList parseFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return newBuilder().mergeFrom(input, extensionRegistry) - .buildParsed(); - } - public static com.alibaba.rocketmq.remoting.protocol.RemotingProtos.StringList parseDelimitedFrom(java.io.InputStream input) - throws java.io.IOException { - Builder builder = newBuilder(); - if (builder.mergeDelimitedFrom(input)) { - return builder.buildParsed(); - } else { - return null; - } - } - public static com.alibaba.rocketmq.remoting.protocol.RemotingProtos.StringList parseDelimitedFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - Builder builder = newBuilder(); - if (builder.mergeDelimitedFrom(input, extensionRegistry)) { - return builder.buildParsed(); - } else { - return null; - } - } - public static com.alibaba.rocketmq.remoting.protocol.RemotingProtos.StringList parseFrom( - com.google.protobuf.CodedInputStream input) - throws java.io.IOException { - return newBuilder().mergeFrom(input).buildParsed(); - } - public static com.alibaba.rocketmq.remoting.protocol.RemotingProtos.StringList parseFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return newBuilder().mergeFrom(input, extensionRegistry) - .buildParsed(); - } - - public static Builder newBuilder() { return Builder.create(); } - public Builder newBuilderForType() { return newBuilder(); } - public static Builder newBuilder(com.alibaba.rocketmq.remoting.protocol.RemotingProtos.StringList prototype) { - return newBuilder().mergeFrom(prototype); - } - public Builder toBuilder() { return newBuilder(this); } - - @java.lang.Override - protected Builder newBuilderForType( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - Builder builder = new Builder(parent); - return builder; - } - public static final class Builder extends - com.google.protobuf.GeneratedMessage.Builder - implements com.alibaba.rocketmq.remoting.protocol.RemotingProtos.StringListOrBuilder { - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return com.alibaba.rocketmq.remoting.protocol.RemotingProtos.internal_static_remoting_StringList_descriptor; - } - - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return com.alibaba.rocketmq.remoting.protocol.RemotingProtos.internal_static_remoting_StringList_fieldAccessorTable; - } - - // Construct using com.alibaba.rocketmq.remoting.protocol.RemotingProtos.StringList.newBuilder() - private Builder() { - maybeForceBuilderInitialization(); - } - - private Builder(BuilderParent parent) { - super(parent); - maybeForceBuilderInitialization(); - } - private void maybeForceBuilderInitialization() { - if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) { - } - } - private static Builder create() { - return new Builder(); - } - - public Builder clear() { - super.clear(); - name_ = com.google.protobuf.LazyStringArrayList.EMPTY; - bitField0_ = (bitField0_ & ~0x00000001); - return this; - } - - public Builder clone() { - return create().mergeFrom(buildPartial()); - } - - public com.google.protobuf.Descriptors.Descriptor - getDescriptorForType() { - return com.alibaba.rocketmq.remoting.protocol.RemotingProtos.StringList.getDescriptor(); - } - - public com.alibaba.rocketmq.remoting.protocol.RemotingProtos.StringList getDefaultInstanceForType() { - return com.alibaba.rocketmq.remoting.protocol.RemotingProtos.StringList.getDefaultInstance(); - } - - public com.alibaba.rocketmq.remoting.protocol.RemotingProtos.StringList build() { - com.alibaba.rocketmq.remoting.protocol.RemotingProtos.StringList result = buildPartial(); - if (!result.isInitialized()) { - throw newUninitializedMessageException(result); - } - return result; - } - - private com.alibaba.rocketmq.remoting.protocol.RemotingProtos.StringList buildParsed() - throws com.google.protobuf.InvalidProtocolBufferException { - com.alibaba.rocketmq.remoting.protocol.RemotingProtos.StringList result = buildPartial(); - if (!result.isInitialized()) { - throw newUninitializedMessageException( - result).asInvalidProtocolBufferException(); - } - return result; - } - - public com.alibaba.rocketmq.remoting.protocol.RemotingProtos.StringList buildPartial() { - com.alibaba.rocketmq.remoting.protocol.RemotingProtos.StringList result = new com.alibaba.rocketmq.remoting.protocol.RemotingProtos.StringList(this); - int from_bitField0_ = bitField0_; - if (((bitField0_ & 0x00000001) == 0x00000001)) { - name_ = new com.google.protobuf.UnmodifiableLazyStringList( - name_); - bitField0_ = (bitField0_ & ~0x00000001); - } - result.name_ = name_; - onBuilt(); - return result; - } - - public Builder mergeFrom(com.google.protobuf.Message other) { - if (other instanceof com.alibaba.rocketmq.remoting.protocol.RemotingProtos.StringList) { - return mergeFrom((com.alibaba.rocketmq.remoting.protocol.RemotingProtos.StringList)other); - } else { - super.mergeFrom(other); - return this; - } - } - - public Builder mergeFrom(com.alibaba.rocketmq.remoting.protocol.RemotingProtos.StringList other) { - if (other == com.alibaba.rocketmq.remoting.protocol.RemotingProtos.StringList.getDefaultInstance()) return this; - if (!other.name_.isEmpty()) { - if (name_.isEmpty()) { - name_ = other.name_; - bitField0_ = (bitField0_ & ~0x00000001); - } else { - ensureNameIsMutable(); - name_.addAll(other.name_); - } - onChanged(); - } - this.mergeUnknownFields(other.getUnknownFields()); - return this; - } - - public final boolean isInitialized() { - return true; - } - - public Builder mergeFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - com.google.protobuf.UnknownFieldSet.Builder unknownFields = - com.google.protobuf.UnknownFieldSet.newBuilder( - this.getUnknownFields()); - while (true) { - int tag = input.readTag(); - switch (tag) { - case 0: - this.setUnknownFields(unknownFields.build()); - onChanged(); - return this; - default: { - if (!parseUnknownField(input, unknownFields, - extensionRegistry, tag)) { - this.setUnknownFields(unknownFields.build()); - onChanged(); - return this; - } - break; - } - case 10: { - ensureNameIsMutable(); - name_.add(input.readBytes()); - break; - } - } - } - } - - private int bitField0_; - - // repeated string name = 1; - private com.google.protobuf.LazyStringList name_ = com.google.protobuf.LazyStringArrayList.EMPTY; - private void ensureNameIsMutable() { - if (!((bitField0_ & 0x00000001) == 0x00000001)) { - name_ = new com.google.protobuf.LazyStringArrayList(name_); - bitField0_ |= 0x00000001; - } - } - public java.util.List - getNameList() { - return java.util.Collections.unmodifiableList(name_); - } - public int getNameCount() { - return name_.size(); - } - public String getName(int index) { - return name_.get(index); - } - public Builder setName( - int index, String value) { - if (value == null) { - throw new NullPointerException(); - } - ensureNameIsMutable(); - name_.set(index, value); - onChanged(); - return this; - } - public Builder addName(String value) { - if (value == null) { - throw new NullPointerException(); - } - ensureNameIsMutable(); - name_.add(value); - onChanged(); - return this; - } - public Builder addAllName( - java.lang.Iterable values) { - ensureNameIsMutable(); - super.addAll(values, name_); - onChanged(); - return this; - } - public Builder clearName() { - name_ = com.google.protobuf.LazyStringArrayList.EMPTY; - bitField0_ = (bitField0_ & ~0x00000001); - onChanged(); - return this; - } - void addName(com.google.protobuf.ByteString value) { - ensureNameIsMutable(); - name_.add(value); - onChanged(); - } - - // @@protoc_insertion_point(builder_scope:remoting.StringList) - } - - static { - defaultInstance = new StringList(true); - defaultInstance.initFields(); - } - - // @@protoc_insertion_point(class_scope:remoting.StringList) - } - - public interface CommandHeaderOrBuilder - extends com.google.protobuf.MessageOrBuilder { - - // required int32 code = 1; - boolean hasCode(); - int getCode(); - - // required .remoting.LanguageCode language = 2; - boolean hasLanguage(); - com.alibaba.rocketmq.remoting.protocol.RemotingProtos.LanguageCode getLanguage(); - - // required int32 version = 3; - boolean hasVersion(); - int getVersion(); - - // required int32 opaque = 4; - boolean hasOpaque(); - int getOpaque(); - - // required int32 flag = 5; - boolean hasFlag(); - int getFlag(); - - // optional string remark = 6; - boolean hasRemark(); - String getRemark(); - - // repeated .remoting.NVPair extFields = 7; - java.util.List - getExtFieldsList(); - com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPair getExtFields(int index); - int getExtFieldsCount(); - java.util.List - getExtFieldsOrBuilderList(); - com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPairOrBuilder getExtFieldsOrBuilder( - int index); - } - public static final class CommandHeader extends - com.google.protobuf.GeneratedMessage - implements CommandHeaderOrBuilder { - // Use CommandHeader.newBuilder() to construct. - private CommandHeader(Builder builder) { - super(builder); - } - private CommandHeader(boolean noInit) {} - - private static final CommandHeader defaultInstance; - public static CommandHeader getDefaultInstance() { - return defaultInstance; - } - - public CommandHeader getDefaultInstanceForType() { - return defaultInstance; - } - - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return com.alibaba.rocketmq.remoting.protocol.RemotingProtos.internal_static_remoting_CommandHeader_descriptor; - } - - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return com.alibaba.rocketmq.remoting.protocol.RemotingProtos.internal_static_remoting_CommandHeader_fieldAccessorTable; - } - - private int bitField0_; - // required int32 code = 1; - public static final int CODE_FIELD_NUMBER = 1; - private int code_; - public boolean hasCode() { - return ((bitField0_ & 0x00000001) == 0x00000001); - } - public int getCode() { - return code_; - } - - // required .remoting.LanguageCode language = 2; - public static final int LANGUAGE_FIELD_NUMBER = 2; - private com.alibaba.rocketmq.remoting.protocol.RemotingProtos.LanguageCode language_; - public boolean hasLanguage() { - return ((bitField0_ & 0x00000002) == 0x00000002); - } - public com.alibaba.rocketmq.remoting.protocol.RemotingProtos.LanguageCode getLanguage() { - return language_; - } - - // required int32 version = 3; - public static final int VERSION_FIELD_NUMBER = 3; - private int version_; - public boolean hasVersion() { - return ((bitField0_ & 0x00000004) == 0x00000004); - } - public int getVersion() { - return version_; - } - - // required int32 opaque = 4; - public static final int OPAQUE_FIELD_NUMBER = 4; - private int opaque_; - public boolean hasOpaque() { - return ((bitField0_ & 0x00000008) == 0x00000008); - } - public int getOpaque() { - return opaque_; - } - - // required int32 flag = 5; - public static final int FLAG_FIELD_NUMBER = 5; - private int flag_; - public boolean hasFlag() { - return ((bitField0_ & 0x00000010) == 0x00000010); - } - public int getFlag() { - return flag_; - } - - // optional string remark = 6; - public static final int REMARK_FIELD_NUMBER = 6; - private java.lang.Object remark_; - public boolean hasRemark() { - return ((bitField0_ & 0x00000020) == 0x00000020); - } - public String getRemark() { - java.lang.Object ref = remark_; - if (ref instanceof String) { - return (String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - String s = bs.toStringUtf8(); - if (com.google.protobuf.Internal.isValidUtf8(bs)) { - remark_ = s; - } - return s; - } - } - private com.google.protobuf.ByteString getRemarkBytes() { - java.lang.Object ref = remark_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8((String) ref); - remark_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - // repeated .remoting.NVPair extFields = 7; - public static final int EXTFIELDS_FIELD_NUMBER = 7; - private java.util.List extFields_; - public java.util.List getExtFieldsList() { - return extFields_; - } - public java.util.List - getExtFieldsOrBuilderList() { - return extFields_; - } - public int getExtFieldsCount() { - return extFields_.size(); - } - public com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPair getExtFields(int index) { - return extFields_.get(index); - } - public com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPairOrBuilder getExtFieldsOrBuilder( - int index) { - return extFields_.get(index); - } - - private void initFields() { - code_ = 0; - language_ = com.alibaba.rocketmq.remoting.protocol.RemotingProtos.LanguageCode.JAVA; - version_ = 0; - opaque_ = 0; - flag_ = 0; - remark_ = ""; - extFields_ = java.util.Collections.emptyList(); - } - private byte memoizedIsInitialized = -1; - public final boolean isInitialized() { - byte isInitialized = memoizedIsInitialized; - if (isInitialized != -1) return isInitialized == 1; - - if (!hasCode()) { - memoizedIsInitialized = 0; - return false; - } - if (!hasLanguage()) { - memoizedIsInitialized = 0; - return false; - } - if (!hasVersion()) { - memoizedIsInitialized = 0; - return false; - } - if (!hasOpaque()) { - memoizedIsInitialized = 0; - return false; - } - if (!hasFlag()) { - memoizedIsInitialized = 0; - return false; - } - for (int i = 0; i < getExtFieldsCount(); i++) { - if (!getExtFields(i).isInitialized()) { - memoizedIsInitialized = 0; - return false; - } - } - memoizedIsInitialized = 1; - return true; - } - - public void writeTo(com.google.protobuf.CodedOutputStream output) - throws java.io.IOException { - getSerializedSize(); - if (((bitField0_ & 0x00000001) == 0x00000001)) { - output.writeInt32(1, code_); - } - if (((bitField0_ & 0x00000002) == 0x00000002)) { - output.writeEnum(2, language_.getNumber()); - } - if (((bitField0_ & 0x00000004) == 0x00000004)) { - output.writeInt32(3, version_); - } - if (((bitField0_ & 0x00000008) == 0x00000008)) { - output.writeInt32(4, opaque_); - } - if (((bitField0_ & 0x00000010) == 0x00000010)) { - output.writeInt32(5, flag_); - } - if (((bitField0_ & 0x00000020) == 0x00000020)) { - output.writeBytes(6, getRemarkBytes()); - } - for (int i = 0; i < extFields_.size(); i++) { - output.writeMessage(7, extFields_.get(i)); - } - getUnknownFields().writeTo(output); - } - - private int memoizedSerializedSize = -1; - public int getSerializedSize() { - int size = memoizedSerializedSize; - if (size != -1) return size; - - size = 0; - if (((bitField0_ & 0x00000001) == 0x00000001)) { - size += com.google.protobuf.CodedOutputStream - .computeInt32Size(1, code_); - } - if (((bitField0_ & 0x00000002) == 0x00000002)) { - size += com.google.protobuf.CodedOutputStream - .computeEnumSize(2, language_.getNumber()); - } - if (((bitField0_ & 0x00000004) == 0x00000004)) { - size += com.google.protobuf.CodedOutputStream - .computeInt32Size(3, version_); - } - if (((bitField0_ & 0x00000008) == 0x00000008)) { - size += com.google.protobuf.CodedOutputStream - .computeInt32Size(4, opaque_); - } - if (((bitField0_ & 0x00000010) == 0x00000010)) { - size += com.google.protobuf.CodedOutputStream - .computeInt32Size(5, flag_); - } - if (((bitField0_ & 0x00000020) == 0x00000020)) { - size += com.google.protobuf.CodedOutputStream - .computeBytesSize(6, getRemarkBytes()); - } - for (int i = 0; i < extFields_.size(); i++) { - size += com.google.protobuf.CodedOutputStream - .computeMessageSize(7, extFields_.get(i)); - } - size += getUnknownFields().getSerializedSize(); - memoizedSerializedSize = size; - return size; - } - - private static final long serialVersionUID = 0L; - @java.lang.Override - protected java.lang.Object writeReplace() - throws java.io.ObjectStreamException { - return super.writeReplace(); - } - - public static com.alibaba.rocketmq.remoting.protocol.RemotingProtos.CommandHeader parseFrom( - com.google.protobuf.ByteString data) - throws com.google.protobuf.InvalidProtocolBufferException { - return newBuilder().mergeFrom(data).buildParsed(); - } - public static com.alibaba.rocketmq.remoting.protocol.RemotingProtos.CommandHeader parseFrom( - com.google.protobuf.ByteString data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return newBuilder().mergeFrom(data, extensionRegistry) - .buildParsed(); - } - public static com.alibaba.rocketmq.remoting.protocol.RemotingProtos.CommandHeader parseFrom(byte[] data) - throws com.google.protobuf.InvalidProtocolBufferException { - return newBuilder().mergeFrom(data).buildParsed(); - } - public static com.alibaba.rocketmq.remoting.protocol.RemotingProtos.CommandHeader parseFrom( - byte[] data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return newBuilder().mergeFrom(data, extensionRegistry) - .buildParsed(); - } - public static com.alibaba.rocketmq.remoting.protocol.RemotingProtos.CommandHeader parseFrom(java.io.InputStream input) - throws java.io.IOException { - return newBuilder().mergeFrom(input).buildParsed(); - } - public static com.alibaba.rocketmq.remoting.protocol.RemotingProtos.CommandHeader parseFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return newBuilder().mergeFrom(input, extensionRegistry) - .buildParsed(); - } - public static com.alibaba.rocketmq.remoting.protocol.RemotingProtos.CommandHeader parseDelimitedFrom(java.io.InputStream input) - throws java.io.IOException { - Builder builder = newBuilder(); - if (builder.mergeDelimitedFrom(input)) { - return builder.buildParsed(); - } else { - return null; - } - } - public static com.alibaba.rocketmq.remoting.protocol.RemotingProtos.CommandHeader parseDelimitedFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - Builder builder = newBuilder(); - if (builder.mergeDelimitedFrom(input, extensionRegistry)) { - return builder.buildParsed(); - } else { - return null; - } - } - public static com.alibaba.rocketmq.remoting.protocol.RemotingProtos.CommandHeader parseFrom( - com.google.protobuf.CodedInputStream input) - throws java.io.IOException { - return newBuilder().mergeFrom(input).buildParsed(); - } - public static com.alibaba.rocketmq.remoting.protocol.RemotingProtos.CommandHeader parseFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return newBuilder().mergeFrom(input, extensionRegistry) - .buildParsed(); - } - - public static Builder newBuilder() { return Builder.create(); } - public Builder newBuilderForType() { return newBuilder(); } - public static Builder newBuilder(com.alibaba.rocketmq.remoting.protocol.RemotingProtos.CommandHeader prototype) { - return newBuilder().mergeFrom(prototype); - } - public Builder toBuilder() { return newBuilder(this); } - - @java.lang.Override - protected Builder newBuilderForType( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - Builder builder = new Builder(parent); - return builder; - } - public static final class Builder extends - com.google.protobuf.GeneratedMessage.Builder - implements com.alibaba.rocketmq.remoting.protocol.RemotingProtos.CommandHeaderOrBuilder { - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return com.alibaba.rocketmq.remoting.protocol.RemotingProtos.internal_static_remoting_CommandHeader_descriptor; - } - - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return com.alibaba.rocketmq.remoting.protocol.RemotingProtos.internal_static_remoting_CommandHeader_fieldAccessorTable; - } - - // Construct using com.alibaba.rocketmq.remoting.protocol.RemotingProtos.CommandHeader.newBuilder() - private Builder() { - maybeForceBuilderInitialization(); - } - - private Builder(BuilderParent parent) { - super(parent); - maybeForceBuilderInitialization(); - } - private void maybeForceBuilderInitialization() { - if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) { - getExtFieldsFieldBuilder(); - } - } - private static Builder create() { - return new Builder(); - } - - public Builder clear() { - super.clear(); - code_ = 0; - bitField0_ = (bitField0_ & ~0x00000001); - language_ = com.alibaba.rocketmq.remoting.protocol.RemotingProtos.LanguageCode.JAVA; - bitField0_ = (bitField0_ & ~0x00000002); - version_ = 0; - bitField0_ = (bitField0_ & ~0x00000004); - opaque_ = 0; - bitField0_ = (bitField0_ & ~0x00000008); - flag_ = 0; - bitField0_ = (bitField0_ & ~0x00000010); - remark_ = ""; - bitField0_ = (bitField0_ & ~0x00000020); - if (extFieldsBuilder_ == null) { - extFields_ = java.util.Collections.emptyList(); - bitField0_ = (bitField0_ & ~0x00000040); - } else { - extFieldsBuilder_.clear(); - } - return this; - } - - public Builder clone() { - return create().mergeFrom(buildPartial()); - } - - public com.google.protobuf.Descriptors.Descriptor - getDescriptorForType() { - return com.alibaba.rocketmq.remoting.protocol.RemotingProtos.CommandHeader.getDescriptor(); - } - - public com.alibaba.rocketmq.remoting.protocol.RemotingProtos.CommandHeader getDefaultInstanceForType() { - return com.alibaba.rocketmq.remoting.protocol.RemotingProtos.CommandHeader.getDefaultInstance(); - } - - public com.alibaba.rocketmq.remoting.protocol.RemotingProtos.CommandHeader build() { - com.alibaba.rocketmq.remoting.protocol.RemotingProtos.CommandHeader result = buildPartial(); - if (!result.isInitialized()) { - throw newUninitializedMessageException(result); - } - return result; - } - - private com.alibaba.rocketmq.remoting.protocol.RemotingProtos.CommandHeader buildParsed() - throws com.google.protobuf.InvalidProtocolBufferException { - com.alibaba.rocketmq.remoting.protocol.RemotingProtos.CommandHeader result = buildPartial(); - if (!result.isInitialized()) { - throw newUninitializedMessageException( - result).asInvalidProtocolBufferException(); - } - return result; - } - - public com.alibaba.rocketmq.remoting.protocol.RemotingProtos.CommandHeader buildPartial() { - com.alibaba.rocketmq.remoting.protocol.RemotingProtos.CommandHeader result = new com.alibaba.rocketmq.remoting.protocol.RemotingProtos.CommandHeader(this); - int from_bitField0_ = bitField0_; - int to_bitField0_ = 0; - if (((from_bitField0_ & 0x00000001) == 0x00000001)) { - to_bitField0_ |= 0x00000001; - } - result.code_ = code_; - if (((from_bitField0_ & 0x00000002) == 0x00000002)) { - to_bitField0_ |= 0x00000002; - } - result.language_ = language_; - if (((from_bitField0_ & 0x00000004) == 0x00000004)) { - to_bitField0_ |= 0x00000004; - } - result.version_ = version_; - if (((from_bitField0_ & 0x00000008) == 0x00000008)) { - to_bitField0_ |= 0x00000008; - } - result.opaque_ = opaque_; - if (((from_bitField0_ & 0x00000010) == 0x00000010)) { - to_bitField0_ |= 0x00000010; - } - result.flag_ = flag_; - if (((from_bitField0_ & 0x00000020) == 0x00000020)) { - to_bitField0_ |= 0x00000020; - } - result.remark_ = remark_; - if (extFieldsBuilder_ == null) { - if (((bitField0_ & 0x00000040) == 0x00000040)) { - extFields_ = java.util.Collections.unmodifiableList(extFields_); - bitField0_ = (bitField0_ & ~0x00000040); - } - result.extFields_ = extFields_; - } else { - result.extFields_ = extFieldsBuilder_.build(); - } - result.bitField0_ = to_bitField0_; - onBuilt(); - return result; - } - - public Builder mergeFrom(com.google.protobuf.Message other) { - if (other instanceof com.alibaba.rocketmq.remoting.protocol.RemotingProtos.CommandHeader) { - return mergeFrom((com.alibaba.rocketmq.remoting.protocol.RemotingProtos.CommandHeader)other); - } else { - super.mergeFrom(other); - return this; - } - } - - public Builder mergeFrom(com.alibaba.rocketmq.remoting.protocol.RemotingProtos.CommandHeader other) { - if (other == com.alibaba.rocketmq.remoting.protocol.RemotingProtos.CommandHeader.getDefaultInstance()) return this; - if (other.hasCode()) { - setCode(other.getCode()); - } - if (other.hasLanguage()) { - setLanguage(other.getLanguage()); - } - if (other.hasVersion()) { - setVersion(other.getVersion()); - } - if (other.hasOpaque()) { - setOpaque(other.getOpaque()); - } - if (other.hasFlag()) { - setFlag(other.getFlag()); - } - if (other.hasRemark()) { - setRemark(other.getRemark()); - } - if (extFieldsBuilder_ == null) { - if (!other.extFields_.isEmpty()) { - if (extFields_.isEmpty()) { - extFields_ = other.extFields_; - bitField0_ = (bitField0_ & ~0x00000040); - } else { - ensureExtFieldsIsMutable(); - extFields_.addAll(other.extFields_); - } - onChanged(); - } - } else { - if (!other.extFields_.isEmpty()) { - if (extFieldsBuilder_.isEmpty()) { - extFieldsBuilder_.dispose(); - extFieldsBuilder_ = null; - extFields_ = other.extFields_; - bitField0_ = (bitField0_ & ~0x00000040); - extFieldsBuilder_ = - com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders ? - getExtFieldsFieldBuilder() : null; - } else { - extFieldsBuilder_.addAllMessages(other.extFields_); - } - } - } - this.mergeUnknownFields(other.getUnknownFields()); - return this; - } - - public final boolean isInitialized() { - if (!hasCode()) { - - return false; - } - if (!hasLanguage()) { - - return false; - } - if (!hasVersion()) { - - return false; - } - if (!hasOpaque()) { - - return false; - } - if (!hasFlag()) { - - return false; - } - for (int i = 0; i < getExtFieldsCount(); i++) { - if (!getExtFields(i).isInitialized()) { - - return false; - } - } - return true; - } - - public Builder mergeFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - com.google.protobuf.UnknownFieldSet.Builder unknownFields = - com.google.protobuf.UnknownFieldSet.newBuilder( - this.getUnknownFields()); - while (true) { - int tag = input.readTag(); - switch (tag) { + + public enum ResponseCode { + // 成功 + SUCCESS(0, 0), + // 发生了未捕获异常 + SYSTEM_ERROR(1, 1), + // 由于线程池拥堵,系统繁忙 + SYSTEM_BUSY(2, 2), + // 请求代码不支持 + REQUEST_CODE_NOT_SUPPORTED(3, 3), ; + + // ///////////////////////////////////////////////////////////////////// + + // 成功 + public static final int SUCCESS_VALUE = 0; + // 发生了未捕获异常 + public static final int SYSTEM_ERROR_VALUE = 1; + // 由于线程池拥堵,系统繁忙 + public static final int SYSTEM_BUSY_VALUE = 2; + // 请求代码不支持 + public static final int REQUEST_CODE_NOT_SUPPORTED_VALUE = 3; + + + public static ResponseCode valueOf(int value) { + switch (value) { case 0: - this.setUnknownFields(unknownFields.build()); - onChanged(); - return this; - default: { - if (!parseUnknownField(input, unknownFields, - extensionRegistry, tag)) { - this.setUnknownFields(unknownFields.build()); - onChanged(); - return this; - } - break; - } - case 8: { - bitField0_ |= 0x00000001; - code_ = input.readInt32(); - break; - } - case 16: { - int rawValue = input.readEnum(); - com.alibaba.rocketmq.remoting.protocol.RemotingProtos.LanguageCode value = com.alibaba.rocketmq.remoting.protocol.RemotingProtos.LanguageCode.valueOf(rawValue); - if (value == null) { - unknownFields.mergeVarintField(2, rawValue); - } else { - bitField0_ |= 0x00000002; - language_ = value; - } - break; - } - case 24: { - bitField0_ |= 0x00000004; - version_ = input.readInt32(); - break; - } - case 32: { - bitField0_ |= 0x00000008; - opaque_ = input.readInt32(); - break; - } - case 40: { - bitField0_ |= 0x00000010; - flag_ = input.readInt32(); - break; - } - case 50: { - bitField0_ |= 0x00000020; - remark_ = input.readBytes(); - break; - } - case 58: { - com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPair.Builder subBuilder = com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPair.newBuilder(); - input.readMessage(subBuilder, extensionRegistry); - addExtFields(subBuilder.buildPartial()); - break; + return SUCCESS; + case 1: + return SYSTEM_ERROR; + case 2: + return SYSTEM_BUSY; + case 3: + return REQUEST_CODE_NOT_SUPPORTED; + default: + return null; } - } } - } - - private int bitField0_; - - // required int32 code = 1; - private int code_ ; - public boolean hasCode() { - return ((bitField0_ & 0x00000001) == 0x00000001); - } - public int getCode() { - return code_; - } - public Builder setCode(int value) { - bitField0_ |= 0x00000001; - code_ = value; - onChanged(); - return this; - } - public Builder clearCode() { - bitField0_ = (bitField0_ & ~0x00000001); - code_ = 0; - onChanged(); - return this; - } - - // required .remoting.LanguageCode language = 2; - private com.alibaba.rocketmq.remoting.protocol.RemotingProtos.LanguageCode language_ = com.alibaba.rocketmq.remoting.protocol.RemotingProtos.LanguageCode.JAVA; - public boolean hasLanguage() { - return ((bitField0_ & 0x00000002) == 0x00000002); - } - public com.alibaba.rocketmq.remoting.protocol.RemotingProtos.LanguageCode getLanguage() { - return language_; - } - public Builder setLanguage(com.alibaba.rocketmq.remoting.protocol.RemotingProtos.LanguageCode value) { - if (value == null) { - throw new NullPointerException(); - } - bitField0_ |= 0x00000002; - language_ = value; - onChanged(); - return this; - } - public Builder clearLanguage() { - bitField0_ = (bitField0_ & ~0x00000002); - language_ = com.alibaba.rocketmq.remoting.protocol.RemotingProtos.LanguageCode.JAVA; - onChanged(); - return this; - } - - // required int32 version = 3; - private int version_ ; - public boolean hasVersion() { - return ((bitField0_ & 0x00000004) == 0x00000004); - } - public int getVersion() { - return version_; - } - public Builder setVersion(int value) { - bitField0_ |= 0x00000004; - version_ = value; - onChanged(); - return this; - } - public Builder clearVersion() { - bitField0_ = (bitField0_ & ~0x00000004); - version_ = 0; - onChanged(); - return this; - } - - // required int32 opaque = 4; - private int opaque_ ; - public boolean hasOpaque() { - return ((bitField0_ & 0x00000008) == 0x00000008); - } - public int getOpaque() { - return opaque_; - } - public Builder setOpaque(int value) { - bitField0_ |= 0x00000008; - opaque_ = value; - onChanged(); - return this; - } - public Builder clearOpaque() { - bitField0_ = (bitField0_ & ~0x00000008); - opaque_ = 0; - onChanged(); - return this; - } - - // required int32 flag = 5; - private int flag_ ; - public boolean hasFlag() { - return ((bitField0_ & 0x00000010) == 0x00000010); - } - public int getFlag() { - return flag_; - } - public Builder setFlag(int value) { - bitField0_ |= 0x00000010; - flag_ = value; - onChanged(); - return this; - } - public Builder clearFlag() { - bitField0_ = (bitField0_ & ~0x00000010); - flag_ = 0; - onChanged(); - return this; - } - - // optional string remark = 6; - private java.lang.Object remark_ = ""; - public boolean hasRemark() { - return ((bitField0_ & 0x00000020) == 0x00000020); - } - public String getRemark() { - java.lang.Object ref = remark_; - if (!(ref instanceof String)) { - String s = ((com.google.protobuf.ByteString) ref).toStringUtf8(); - remark_ = s; - return s; - } else { - return (String) ref; - } - } - public Builder setRemark(String value) { - if (value == null) { - throw new NullPointerException(); - } - bitField0_ |= 0x00000020; - remark_ = value; - onChanged(); - return this; - } - public Builder clearRemark() { - bitField0_ = (bitField0_ & ~0x00000020); - remark_ = getDefaultInstance().getRemark(); - onChanged(); - return this; - } - void setRemark(com.google.protobuf.ByteString value) { - bitField0_ |= 0x00000020; - remark_ = value; - onChanged(); - } - - // repeated .remoting.NVPair extFields = 7; - private java.util.List extFields_ = - java.util.Collections.emptyList(); - private void ensureExtFieldsIsMutable() { - if (!((bitField0_ & 0x00000040) == 0x00000040)) { - extFields_ = new java.util.ArrayList(extFields_); - bitField0_ |= 0x00000040; - } - } - - private com.google.protobuf.RepeatedFieldBuilder< - com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPair, com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPair.Builder, com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPairOrBuilder> extFieldsBuilder_; - - public java.util.List getExtFieldsList() { - if (extFieldsBuilder_ == null) { - return java.util.Collections.unmodifiableList(extFields_); - } else { - return extFieldsBuilder_.getMessageList(); - } - } - public int getExtFieldsCount() { - if (extFieldsBuilder_ == null) { - return extFields_.size(); - } else { - return extFieldsBuilder_.getCount(); - } - } - public com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPair getExtFields(int index) { - if (extFieldsBuilder_ == null) { - return extFields_.get(index); - } else { - return extFieldsBuilder_.getMessage(index); - } - } - public Builder setExtFields( - int index, com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPair value) { - if (extFieldsBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - ensureExtFieldsIsMutable(); - extFields_.set(index, value); - onChanged(); - } else { - extFieldsBuilder_.setMessage(index, value); - } - return this; - } - public Builder setExtFields( - int index, com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPair.Builder builderForValue) { - if (extFieldsBuilder_ == null) { - ensureExtFieldsIsMutable(); - extFields_.set(index, builderForValue.build()); - onChanged(); - } else { - extFieldsBuilder_.setMessage(index, builderForValue.build()); - } - return this; - } - public Builder addExtFields(com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPair value) { - if (extFieldsBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - ensureExtFieldsIsMutable(); - extFields_.add(value); - onChanged(); - } else { - extFieldsBuilder_.addMessage(value); - } - return this; - } - public Builder addExtFields( - int index, com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPair value) { - if (extFieldsBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - ensureExtFieldsIsMutable(); - extFields_.add(index, value); - onChanged(); - } else { - extFieldsBuilder_.addMessage(index, value); - } - return this; - } - public Builder addExtFields( - com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPair.Builder builderForValue) { - if (extFieldsBuilder_ == null) { - ensureExtFieldsIsMutable(); - extFields_.add(builderForValue.build()); - onChanged(); - } else { - extFieldsBuilder_.addMessage(builderForValue.build()); - } - return this; - } - public Builder addExtFields( - int index, com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPair.Builder builderForValue) { - if (extFieldsBuilder_ == null) { - ensureExtFieldsIsMutable(); - extFields_.add(index, builderForValue.build()); - onChanged(); - } else { - extFieldsBuilder_.addMessage(index, builderForValue.build()); - } - return this; - } - public Builder addAllExtFields( - java.lang.Iterable values) { - if (extFieldsBuilder_ == null) { - ensureExtFieldsIsMutable(); - super.addAll(values, extFields_); - onChanged(); - } else { - extFieldsBuilder_.addAllMessages(values); - } - return this; - } - public Builder clearExtFields() { - if (extFieldsBuilder_ == null) { - extFields_ = java.util.Collections.emptyList(); - bitField0_ = (bitField0_ & ~0x00000040); - onChanged(); - } else { - extFieldsBuilder_.clear(); - } - return this; - } - public Builder removeExtFields(int index) { - if (extFieldsBuilder_ == null) { - ensureExtFieldsIsMutable(); - extFields_.remove(index); - onChanged(); - } else { - extFieldsBuilder_.remove(index); - } - return this; - } - public com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPair.Builder getExtFieldsBuilder( - int index) { - return getExtFieldsFieldBuilder().getBuilder(index); - } - public com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPairOrBuilder getExtFieldsOrBuilder( - int index) { - if (extFieldsBuilder_ == null) { - return extFields_.get(index); } else { - return extFieldsBuilder_.getMessageOrBuilder(index); + + private final int index; + private final int value; + + + public final int getNumber() { + return value; } - } - public java.util.List - getExtFieldsOrBuilderList() { - if (extFieldsBuilder_ != null) { - return extFieldsBuilder_.getMessageOrBuilderList(); - } else { - return java.util.Collections.unmodifiableList(extFields_); + + + public int getIndex() { + return index; } - } - public com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPair.Builder addExtFieldsBuilder() { - return getExtFieldsFieldBuilder().addBuilder( - com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPair.getDefaultInstance()); - } - public com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPair.Builder addExtFieldsBuilder( - int index) { - return getExtFieldsFieldBuilder().addBuilder( - index, com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPair.getDefaultInstance()); - } - public java.util.List - getExtFieldsBuilderList() { - return getExtFieldsFieldBuilder().getBuilderList(); - } - private com.google.protobuf.RepeatedFieldBuilder< - com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPair, com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPair.Builder, com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPairOrBuilder> - getExtFieldsFieldBuilder() { - if (extFieldsBuilder_ == null) { - extFieldsBuilder_ = new com.google.protobuf.RepeatedFieldBuilder< - com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPair, com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPair.Builder, com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPairOrBuilder>( - extFields_, - ((bitField0_ & 0x00000040) == 0x00000040), - getParentForChildren(), - isClean()); - extFields_ = null; + + + private ResponseCode(int index, int value) { + this.index = index; + this.value = value; } - return extFieldsBuilder_; - } - - // @@protoc_insertion_point(builder_scope:remoting.CommandHeader) - } - - static { - defaultInstance = new CommandHeader(true); - defaultInstance.initFields(); + } - - // @@protoc_insertion_point(class_scope:remoting.CommandHeader) - } - - private static com.google.protobuf.Descriptors.Descriptor - internal_static_remoting_KVPair_descriptor; - private static - com.google.protobuf.GeneratedMessage.FieldAccessorTable - internal_static_remoting_KVPair_fieldAccessorTable; - private static com.google.protobuf.Descriptors.Descriptor - internal_static_remoting_KVPairList_descriptor; - private static - com.google.protobuf.GeneratedMessage.FieldAccessorTable - internal_static_remoting_KVPairList_fieldAccessorTable; - private static com.google.protobuf.Descriptors.Descriptor - internal_static_remoting_NVPair_descriptor; - private static - com.google.protobuf.GeneratedMessage.FieldAccessorTable - internal_static_remoting_NVPair_fieldAccessorTable; - private static com.google.protobuf.Descriptors.Descriptor - internal_static_remoting_NVPairList_descriptor; - private static - com.google.protobuf.GeneratedMessage.FieldAccessorTable - internal_static_remoting_NVPairList_fieldAccessorTable; - private static com.google.protobuf.Descriptors.Descriptor - internal_static_remoting_StringList_descriptor; - private static - com.google.protobuf.GeneratedMessage.FieldAccessorTable - internal_static_remoting_StringList_fieldAccessorTable; - private static com.google.protobuf.Descriptors.Descriptor - internal_static_remoting_CommandHeader_descriptor; - private static - com.google.protobuf.GeneratedMessage.FieldAccessorTable - internal_static_remoting_CommandHeader_fieldAccessorTable; - - public static com.google.protobuf.Descriptors.FileDescriptor - getDescriptor() { - return descriptor; - } - private static com.google.protobuf.Descriptors.FileDescriptor - descriptor; - static { - java.lang.String[] descriptorData = { - "\n\016remoting.proto\022\010remoting\"$\n\006KVPair\022\013\n\003" + - "key\030\001 \002(\005\022\r\n\005value\030\002 \002(\t\".\n\nKVPairList\022 " + - "\n\006fields\030\001 \003(\0132\020.remoting.KVPair\"%\n\006NVPa" + - "ir\022\014\n\004name\030\001 \002(\t\022\r\n\005value\030\002 \002(\t\".\n\nNVPai" + - "rList\022 \n\006fields\030\001 \003(\0132\020.remoting.NVPair\"" + - "\032\n\nStringList\022\014\n\004name\030\001 \003(\t\"\253\001\n\rCommandH" + - "eader\022\014\n\004code\030\001 \002(\005\022(\n\010language\030\002 \002(\0162\026." + - "remoting.LanguageCode\022\017\n\007version\030\003 \002(\005\022\016" + - "\n\006opaque\030\004 \002(\005\022\014\n\004flag\030\005 \002(\005\022\016\n\006remark\030\006" + - " \001(\t\022#\n\textFields\030\007 \003(\0132\020.remoting.NVPai", - "r*f\n\014LanguageCode\022\010\n\004JAVA\020\000\022\007\n\003CPP\020\001\022\n\n\006" + - "DOTNET\020\002\022\n\n\006PYTHON\020\003\022\n\n\006DELPHI\020\004\022\n\n\006ERLA" + - "NG\020\005\022\010\n\004RUBY\020\006\022\t\n\005OTHER\020\007*\'\n\007FlagBit\022\014\n\010" + - "RPC_TYPE\020\000\022\016\n\nRPC_ONEWAY\020\001*\037\n\013RequestCod" + - "e\022\020\n\014DEMO_REQUEST\020\000*^\n\014ResponseCode\022\013\n\007S" + - "UCCESS\020\000\022\020\n\014SYSTEM_ERROR\020\001\022\017\n\013SYSTEM_BUS" + - "Y\020\002\022\036\n\032REQUEST_CODE_NOT_SUPPORTED\020\003B:\n&c" + - "om.alibaba.rocketmq.remoting.protocolB\016R" + - "emotingProtosH\001" - }; - com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner = - new com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner() { - public com.google.protobuf.ExtensionRegistry assignDescriptors( - com.google.protobuf.Descriptors.FileDescriptor root) { - descriptor = root; - internal_static_remoting_KVPair_descriptor = - getDescriptor().getMessageTypes().get(0); - internal_static_remoting_KVPair_fieldAccessorTable = new - com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_remoting_KVPair_descriptor, - new java.lang.String[] { "Key", "Value", }, - com.alibaba.rocketmq.remoting.protocol.RemotingProtos.KVPair.class, - com.alibaba.rocketmq.remoting.protocol.RemotingProtos.KVPair.Builder.class); - internal_static_remoting_KVPairList_descriptor = - getDescriptor().getMessageTypes().get(1); - internal_static_remoting_KVPairList_fieldAccessorTable = new - com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_remoting_KVPairList_descriptor, - new java.lang.String[] { "Fields", }, - com.alibaba.rocketmq.remoting.protocol.RemotingProtos.KVPairList.class, - com.alibaba.rocketmq.remoting.protocol.RemotingProtos.KVPairList.Builder.class); - internal_static_remoting_NVPair_descriptor = - getDescriptor().getMessageTypes().get(2); - internal_static_remoting_NVPair_fieldAccessorTable = new - com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_remoting_NVPair_descriptor, - new java.lang.String[] { "Name", "Value", }, - com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPair.class, - com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPair.Builder.class); - internal_static_remoting_NVPairList_descriptor = - getDescriptor().getMessageTypes().get(3); - internal_static_remoting_NVPairList_fieldAccessorTable = new - com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_remoting_NVPairList_descriptor, - new java.lang.String[] { "Fields", }, - com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPairList.class, - com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPairList.Builder.class); - internal_static_remoting_StringList_descriptor = - getDescriptor().getMessageTypes().get(4); - internal_static_remoting_StringList_fieldAccessorTable = new - com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_remoting_StringList_descriptor, - new java.lang.String[] { "Name", }, - com.alibaba.rocketmq.remoting.protocol.RemotingProtos.StringList.class, - com.alibaba.rocketmq.remoting.protocol.RemotingProtos.StringList.Builder.class); - internal_static_remoting_CommandHeader_descriptor = - getDescriptor().getMessageTypes().get(5); - internal_static_remoting_CommandHeader_fieldAccessorTable = new - com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_remoting_CommandHeader_descriptor, - new java.lang.String[] { "Code", "Language", "Version", "Opaque", "Flag", "Remark", "ExtFields", }, - com.alibaba.rocketmq.remoting.protocol.RemotingProtos.CommandHeader.class, - com.alibaba.rocketmq.remoting.protocol.RemotingProtos.CommandHeader.Builder.class); - return null; - } - }; - com.google.protobuf.Descriptors.FileDescriptor - .internalBuildGeneratedFileFrom(descriptorData, - new com.google.protobuf.Descriptors.FileDescriptor[] { - }, assigner); - } - - // @@protoc_insertion_point(outer_class_scope) } diff --git a/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/protocol/RemotingProtosHelper.java b/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/protocol/RemotingProtosHelper.java deleted file mode 100644 index b38e6113..00000000 --- a/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/protocol/RemotingProtosHelper.java +++ /dev/null @@ -1,103 +0,0 @@ -/** - * $Id: RemotingProtosHelper.java 1831 2013-05-16 01:39:51Z shijia.wxr $ - */ -package com.alibaba.rocketmq.remoting.protocol; - -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map.Entry; - -import com.google.protobuf.InvalidProtocolBufferException; -import com.alibaba.rocketmq.remoting.protocol.RemotingProtos.KVPair; -import com.alibaba.rocketmq.remoting.protocol.RemotingProtos.KVPairList; -import com.alibaba.rocketmq.remoting.protocol.RemotingProtos.StringList; - - -/** - * Э鸨 - * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com - * - */ -public class RemotingProtosHelper { - /** - * лַб - */ - public static byte[] stringList2Bytes(final List strs) { - if (null == strs || strs.isEmpty()) { - return null; - } - - StringList.Builder builder = StringList.newBuilder(); - - for (String str : strs) { - builder.addName(str); - } - - return builder.build().toByteArray(); - } - - - /** - * лַб - */ - public static List bytes2StringList(final byte[] data) throws InvalidProtocolBufferException { - if (null == data) { - return null; - } - StringList stringList = StringList.parseFrom(data); - return stringList.getNameList(); - } - - - /** - * лֵ - */ - public static byte[] hashMap2Bytes(final HashMap nms) { - if (null == nms || nms.isEmpty()) { - return null; - } - - KVPairList.Builder builder = KVPairList.newBuilder(); - - Iterator> it = nms.entrySet().iterator(); - for (int index = 0; it.hasNext(); index++) { - Entry entry = (Entry) it.next(); - int key = entry.getKey(); - String val = entry.getValue(); - - KVPair.Builder kvb = KVPair.newBuilder(); - kvb.setKey(key); - kvb.setValue(val); - builder.addFields(index, kvb.build()); - } - - return builder.build().toByteArray(); - } - - - /** - * лֵ - * - * @throws InvalidProtocolBufferException - */ - public static HashMap bytes2HashMap(final byte[] data) - throws InvalidProtocolBufferException { - if (null == data) { - return null; - } - - HashMap result = new HashMap(); - - KVPairList kvList = KVPairList.parseFrom(data); - - List kvList2 = kvList.getFieldsList(); - - for (KVPair kv : kvList2) { - result.put(kv.getKey(), kv.getValue()); - } - - return result; - } -} diff --git a/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/protocol/RemotingSerializable.java b/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/protocol/RemotingSerializable.java new file mode 100644 index 00000000..037e34b2 --- /dev/null +++ b/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/protocol/RemotingSerializable.java @@ -0,0 +1,72 @@ +/** + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.rocketmq.remoting.protocol; + +import java.nio.charset.Charset; + +import com.alibaba.fastjson.JSON; + + +/** + * 复杂对象的序列化,利用json来实现 + * + * @author shijia.wxr + * @since 2013-7-13 + */ +public abstract class RemotingSerializable { + public String toJson() { + return toJson(false); + } + + + public String toJson(final boolean prettyFormat) { + return toJson(this, prettyFormat); + } + + + public static String toJson(final Object obj, boolean prettyFormat) { + return JSON.toJSONString(obj, prettyFormat); + } + + + public static T fromJson(String json, Class classOfT) { + return JSON.parseObject(json, classOfT); + } + + + public byte[] encode() { + final String json = this.toJson(); + if (json != null) { + return json.getBytes(); + } + return null; + } + + + public static byte[] encode(final Object obj) { + final String json = toJson(obj, false); + if (json != null) { + return json.getBytes(Charset.forName("UTF-8")); + } + return null; + } + + + public static T decode(final byte[] data, Class classOfT) { + final String json = new String(data, Charset.forName("UTF-8")); + return fromJson(json, classOfT); + } +} diff --git a/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/protocol/generate.bat b/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/protocol/generate.bat deleted file mode 100644 index 5c6149ca..00000000 --- a/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/protocol/generate.bat +++ /dev/null @@ -1,2 +0,0 @@ -protoc.exe -I=./ --java_out=../../../../.. ./remoting.proto -pause \ No newline at end of file diff --git a/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/protocol/protocol.txt b/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/protocol/protocol.txt new file mode 100644 index 00000000..ce055773 --- /dev/null +++ b/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/protocol/protocol.txt @@ -0,0 +1,12 @@ +// +// RemotingͨЭ +// 2013-01-21 19:11:14 ļ V0.1 +// +// Эʽ
+// 1 2 3 4 +// Э4ֱ֣ +// 14ֽ234ܺ +// 24ֽ3ij +// 3ʹjsonл +// 4ӦԶл +// diff --git a/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/protocol/remoting.proto b/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/protocol/remoting.proto deleted file mode 100644 index 6e3b946e..00000000 --- a/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/protocol/remoting.proto +++ /dev/null @@ -1,88 +0,0 @@ -// -// RemotingͨЭ -// 2013-01-21 19:11:14 ļ V0.1 -// -// Эʽ
-// 1 2 3 4 -// Э4ֱ֣ -// 14ֽ234ܺ -// 24ֽ3ij -// 3Google Protobufл -// 4ӦԶл -// -package remoting; -option optimize_for = SPEED; -option java_package = "com.alibaba.rocketmq.remoting.protocol"; -option java_outer_classname = "RemotingProtos"; - -// KV -message KVPair{ - required int32 key=1; - required string value=2; -} - -// KVԼ -message KVPairList{ - repeated KVPair fields=1; -} - -// NV -message NVPair{ - required string name=1; - required string value=2; -} - -// NVԼ -message NVPairList{ - repeated NVPair fields=1; -} - -// ַ -message StringList{ - repeated string name=1; -} - -// -enum LanguageCode{ - JAVA = 0; - CPP = 1; - DOTNET = 2; - PYTHON = 3; - DELPHI = 4; - ERLANG = 5; - RUBY = 6; - OTHER = 7; -} - -// Flagλ -enum FlagBit{ - RPC_TYPE = 0; // 0, REQUEST_COMMAND - // 1, RESPONSE_COMMAND - - RPC_ONEWAY = 1; // 0, RPC - // 1, Oneway -} - -// RPC -enum RequestCode{ - DEMO_REQUEST = 0; -} - -// RPCӦ -enum ResponseCode{ - SUCCESS = 0; // ɹ - SYSTEM_ERROR = 1; // δ쳣 - SYSTEM_BUSY = 2; // ̳߳ӵ£ϵͳæ - REQUEST_CODE_NOT_SUPPORTED = 3; // 벻֧ -} - - -message CommandHeader { - required int32 code = 1; - required LanguageCode language = 2; - required int32 version = 3; - required int32 opaque = 4; - required int32 flag = 5; - optional string remark = 6; - repeated NVPair extFields=7; -} diff --git a/rocketmq-remoting/src/test/java/com/alibaba/rocketmq/protocol/RemotingProtosHelperTest.java b/rocketmq-remoting/src/test/java/com/alibaba/rocketmq/protocol/RemotingProtosHelperTest.java deleted file mode 100644 index a4e1c03e..00000000 --- a/rocketmq-remoting/src/test/java/com/alibaba/rocketmq/protocol/RemotingProtosHelperTest.java +++ /dev/null @@ -1,76 +0,0 @@ -/** - * $Id: RemotingProtosHelperTest.java 1831 2013-05-16 01:39:51Z shijia.wxr $ - */ -package com.alibaba.rocketmq.protocol; - -import static org.junit.Assert.assertTrue; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map.Entry; - -import org.junit.Test; - -import com.google.protobuf.InvalidProtocolBufferException; -import com.alibaba.rocketmq.remoting.protocol.RemotingProtosHelper; - - -/** - * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com - */ -public class RemotingProtosHelperTest { - @Test - public void stringList2Bytes_bytes2StringList() throws InvalidProtocolBufferException { - List strs = new ArrayList(); - strs.add("hello"); - strs.add("hi"); - strs.add("once"); - strs.add("there"); - strs.add("was"); - - byte[] data = RemotingProtosHelper.stringList2Bytes(strs); - assertTrue(data != null); - - // Էл - List strsRead = RemotingProtosHelper.bytes2StringList(data); - - assertTrue(strsRead != null); - assertTrue(strsRead.equals(strs)); - - for (String str : strs) { - System.out.println(str); - } - } - - - @Test - public void hashMap2Bytes_bytes2HashMap() throws InvalidProtocolBufferException { - HashMap nmsWrite = new HashMap(); - nmsWrite.put(1, "hello"); - nmsWrite.put(2, "hi"); - nmsWrite.put(4, "nice"); - nmsWrite.put(6, "nice"); - nmsWrite.put(8, "nice"); - - // л - byte[] data = RemotingProtosHelper.hashMap2Bytes(nmsWrite); - assertTrue(data != null); - - // Էл - HashMap nmsRead = RemotingProtosHelper.bytes2HashMap(data); - - assertTrue(nmsRead != null); - assertTrue(nmsRead.equals(nmsWrite)); - - Iterator> it = nmsRead.entrySet().iterator(); - while (it.hasNext()) { - Entry entry = (Entry) it.next(); - Integer key = entry.getKey(); - String val = entry.getValue(); - System.out.println(key + " " + val); - } - } -} diff --git a/rocketmq-remoting/src/test/java/com/alibaba/rocketmq/remoting/ExceptionTest.java b/rocketmq-remoting/src/test/java/com/alibaba/rocketmq/remoting/ExceptionTest.java index 8a5448fe..fbb5b370 100644 --- a/rocketmq-remoting/src/test/java/com/alibaba/rocketmq/remoting/ExceptionTest.java +++ b/rocketmq-remoting/src/test/java/com/alibaba/rocketmq/remoting/ExceptionTest.java @@ -19,12 +19,10 @@ import com.alibaba.rocketmq.remoting.netty.NettyRequestProcessor; import com.alibaba.rocketmq.remoting.netty.NettyServerConfig; import com.alibaba.rocketmq.remoting.protocol.RemotingCommand; -import com.alibaba.rocketmq.remoting.protocol.RemotingProtos.RequestCode; /** - * @author vintage.wang@gmail.com shijia.wxr@taobao.com - * + * @author shijia.wxr */ public class ExceptionTest { private static RemotingClient createRemotingClient() { @@ -38,7 +36,7 @@ private static RemotingClient createRemotingClient() { private static RemotingServer createRemotingServer() throws InterruptedException { NettyServerConfig config = new NettyServerConfig(); RemotingServer client = new NettyRemotingServer(config); - client.registerProcessor(RequestCode.DEMO_REQUEST_VALUE, new NettyRequestProcessor() { + client.registerProcessor(0, new NettyRequestProcessor() { private int i = 0; @@ -58,7 +56,7 @@ public RemotingCommand processRequest(ChannelHandlerContext ctx, RemotingCommand public void test_CONNECT_EXCEPTION() { RemotingClient client = createRemotingClient(); - RemotingCommand request = RemotingCommand.createRequestCommand(RequestCode.DEMO_REQUEST_VALUE, null); + RemotingCommand request = RemotingCommand.createRequestCommand(0, null); RemotingCommand response = null; try { response = client.invokeSync("127.0.0.1:10911", request, 1000 * 3); diff --git a/rocketmq-remoting/src/test/java/com/alibaba/rocketmq/remoting/MixTest.java b/rocketmq-remoting/src/test/java/com/alibaba/rocketmq/remoting/MixTest.java index c6358f91..57d318db 100644 --- a/rocketmq-remoting/src/test/java/com/alibaba/rocketmq/remoting/MixTest.java +++ b/rocketmq-remoting/src/test/java/com/alibaba/rocketmq/remoting/MixTest.java @@ -7,8 +7,7 @@ /** - * @author vintage.wang@gmail.com shijia.wxr@taobao.com - * + * @author shijia.wxr */ public class MixTest { @Test diff --git a/rocketmq-remoting/src/test/java/com/alibaba/rocketmq/remoting/NettyConnectionTest.java b/rocketmq-remoting/src/test/java/com/alibaba/rocketmq/remoting/NettyConnectionTest.java new file mode 100644 index 00000000..9cd57e8e --- /dev/null +++ b/rocketmq-remoting/src/test/java/com/alibaba/rocketmq/remoting/NettyConnectionTest.java @@ -0,0 +1,47 @@ +package com.alibaba.rocketmq.remoting; + +import org.junit.Test; + +import com.alibaba.rocketmq.remoting.exception.RemotingConnectException; +import com.alibaba.rocketmq.remoting.exception.RemotingSendRequestException; +import com.alibaba.rocketmq.remoting.exception.RemotingTimeoutException; +import com.alibaba.rocketmq.remoting.netty.NettyClientConfig; +import com.alibaba.rocketmq.remoting.netty.NettyRemotingClient; +import com.alibaba.rocketmq.remoting.protocol.RemotingCommand; + + +/** + * 连接超时测试 + * + * @author shijia.wxr + * @since 2013-7-6 + */ +public class NettyConnectionTest { + public static RemotingClient createRemotingClient() { + NettyClientConfig config = new NettyClientConfig(); + config.setClientChannelMaxIdleTimeSeconds(15); + RemotingClient client = new NettyRemotingClient(config); + client.start(); + return client; + } + + + @Test + public void test_connect_timeout() throws InterruptedException, RemotingConnectException, + RemotingSendRequestException, RemotingTimeoutException { + RemotingClient client = createRemotingClient(); + + for (int i = 0; i < 100; i++) { + try { + RemotingCommand request = RemotingCommand.createRequestCommand(0, null); + RemotingCommand response = client.invokeSync("127.0.0.1:8888", request, 1000 * 3); + } + catch (Exception e) { + e.printStackTrace(); + } + } + + client.shutdown(); + System.out.println("-----------------------------------------------------------------"); + } +} diff --git a/rocketmq-remoting/src/test/java/com/alibaba/rocketmq/remoting/NettyIdleTest.java b/rocketmq-remoting/src/test/java/com/alibaba/rocketmq/remoting/NettyIdleTest.java new file mode 100644 index 00000000..a6b190b6 --- /dev/null +++ b/rocketmq-remoting/src/test/java/com/alibaba/rocketmq/remoting/NettyIdleTest.java @@ -0,0 +1,75 @@ +package com.alibaba.rocketmq.remoting; + +import static org.junit.Assert.assertTrue; +import io.netty.channel.ChannelHandlerContext; + +import java.util.concurrent.Executors; + +import com.alibaba.rocketmq.remoting.exception.RemotingConnectException; +import com.alibaba.rocketmq.remoting.exception.RemotingSendRequestException; +import com.alibaba.rocketmq.remoting.exception.RemotingTimeoutException; +import com.alibaba.rocketmq.remoting.netty.NettyClientConfig; +import com.alibaba.rocketmq.remoting.netty.NettyRemotingClient; +import com.alibaba.rocketmq.remoting.netty.NettyRemotingServer; +import com.alibaba.rocketmq.remoting.netty.NettyRequestProcessor; +import com.alibaba.rocketmq.remoting.netty.NettyServerConfig; +import com.alibaba.rocketmq.remoting.protocol.RemotingCommand; + + +/** + * @author shijia.wxr + * @since 2013-7-6 + */ +public class NettyIdleTest { + public static RemotingClient createRemotingClient() { + NettyClientConfig config = new NettyClientConfig(); + config.setClientChannelMaxIdleTimeSeconds(15); + RemotingClient client = new NettyRemotingClient(config); + client.start(); + return client; + } + + + public static RemotingServer createRemotingServer() throws InterruptedException { + NettyServerConfig config = new NettyServerConfig(); + config.setServerChannelMaxIdleTimeSeconds(30); + RemotingServer remotingServer = new NettyRemotingServer(config); + remotingServer.registerProcessor(0, new NettyRequestProcessor() { + private int i = 0; + + + @Override + public RemotingCommand processRequest(ChannelHandlerContext ctx, RemotingCommand request) { + System.out.println("processRequest=" + request + " " + (i++)); + request.setRemark("hello, I am respponse " + ctx.channel().remoteAddress()); + return request; + } + }, Executors.newCachedThreadPool()); + remotingServer.start(); + return remotingServer; + } + + + // @Test + public void test_idle_event() throws InterruptedException, RemotingConnectException, + RemotingSendRequestException, RemotingTimeoutException { + RemotingServer server = createRemotingServer(); + RemotingClient client = createRemotingClient(); + + for (int i = 0; i < 10; i++) { + RemotingCommand request = RemotingCommand.createRequestCommand(0, null); + RemotingCommand response = client.invokeSync("127.0.0.1:8888", request, 1000 * 3); + System.out.println(i + " invoke result = " + response); + assertTrue(response != null); + + Thread.sleep(1000 * 10); + } + + Thread.sleep(1000 * 60); + + client.shutdown(); + server.shutdown(); + System.out.println("-----------------------------------------------------------------"); + } + +} diff --git a/rocketmq-remoting/src/test/java/com/alibaba/rocketmq/remoting/NettyRPCTest.java b/rocketmq-remoting/src/test/java/com/alibaba/rocketmq/remoting/NettyRPCTest.java index a1c26280..90b3187e 100644 --- a/rocketmq-remoting/src/test/java/com/alibaba/rocketmq/remoting/NettyRPCTest.java +++ b/rocketmq-remoting/src/test/java/com/alibaba/rocketmq/remoting/NettyRPCTest.java @@ -10,6 +10,8 @@ import org.junit.Test; +import com.alibaba.rocketmq.remoting.annotation.CFNullable; +import com.alibaba.rocketmq.remoting.exception.RemotingCommandException; import com.alibaba.rocketmq.remoting.exception.RemotingConnectException; import com.alibaba.rocketmq.remoting.exception.RemotingSendRequestException; import com.alibaba.rocketmq.remoting.exception.RemotingTimeoutException; @@ -21,12 +23,10 @@ import com.alibaba.rocketmq.remoting.netty.NettyServerConfig; import com.alibaba.rocketmq.remoting.netty.ResponseFuture; import com.alibaba.rocketmq.remoting.protocol.RemotingCommand; -import com.alibaba.rocketmq.remoting.protocol.RemotingProtos.RequestCode; /** - * @author vintage.wang@gmail.com shijia.wxr@taobao.com - * + * @author shijia.wxr */ public class NettyRPCTest { public static RemotingClient createRemotingClient() { @@ -39,8 +39,8 @@ public static RemotingClient createRemotingClient() { public static RemotingServer createRemotingServer() throws InterruptedException { NettyServerConfig config = new NettyServerConfig(); - RemotingServer client = new NettyRemotingServer(config); - client.registerProcessor(RequestCode.DEMO_REQUEST_VALUE, new NettyRequestProcessor() { + RemotingServer remotingServer = new NettyRemotingServer(config); + remotingServer.registerProcessor(0, new NettyRequestProcessor() { private int i = 0; @@ -51,8 +51,8 @@ public RemotingCommand processRequest(ChannelHandlerContext ctx, RemotingCommand return request; } }, Executors.newCachedThreadPool()); - client.start(); - return client; + remotingServer.start(); + return remotingServer; } @@ -63,8 +63,11 @@ public void test_RPC_Sync() throws InterruptedException, RemotingConnectExceptio RemotingClient client = createRemotingClient(); for (int i = 0; i < 100; i++) { - RemotingCommand request = RemotingCommand.createRequestCommand(RequestCode.DEMO_REQUEST_VALUE, null); - RemotingCommand response = client.invokeSync("127.0.0.1:10911", request, 1000 * 3); + TestRequestHeader requestHeader = new TestRequestHeader(); + requestHeader.setCount(i); + requestHeader.setMessageTitle("HelloMessageTitle"); + RemotingCommand request = RemotingCommand.createRequestCommand(0, requestHeader); + RemotingCommand response = client.invokeSync("127.0.0.1:8888", request, 1000 * 3000); System.out.println("invoke result = " + response); assertTrue(response != null); } @@ -76,15 +79,15 @@ public void test_RPC_Sync() throws InterruptedException, RemotingConnectExceptio @Test - public void test_RPC_Oneway() throws InterruptedException, RemotingConnectException, RemotingTimeoutException, - RemotingTooMuchRequestException, RemotingSendRequestException { + public void test_RPC_Oneway() throws InterruptedException, RemotingConnectException, + RemotingTimeoutException, RemotingTooMuchRequestException, RemotingSendRequestException { RemotingServer server = createRemotingServer(); RemotingClient client = createRemotingClient(); for (int i = 0; i < 100; i++) { - RemotingCommand request = RemotingCommand.createRequestCommand(RequestCode.DEMO_REQUEST_VALUE, null); + RemotingCommand request = RemotingCommand.createRequestCommand(0, null); request.setRemark(String.valueOf(i)); - client.invokeOneway("127.0.0.1:10911", request, 1000 * 3); + client.invokeOneway("127.0.0.1:8888", request, 1000 * 3); } client.shutdown(); @@ -94,15 +97,15 @@ public void test_RPC_Oneway() throws InterruptedException, RemotingConnectExcept @Test - public void test_RPC_Async() throws InterruptedException, RemotingConnectException, RemotingTimeoutException, - RemotingTooMuchRequestException, RemotingSendRequestException { + public void test_RPC_Async() throws InterruptedException, RemotingConnectException, + RemotingTimeoutException, RemotingTooMuchRequestException, RemotingSendRequestException { RemotingServer server = createRemotingServer(); RemotingClient client = createRemotingClient(); for (int i = 0; i < 100; i++) { - RemotingCommand request = RemotingCommand.createRequestCommand(RequestCode.DEMO_REQUEST_VALUE, null); + RemotingCommand request = RemotingCommand.createRequestCommand(0, null); request.setRemark(String.valueOf(i)); - client.invokeAsync("127.0.0.1:10911", request, 1000 * 3, new InvokeCallback() { + client.invokeAsync("127.0.0.1:8888", request, 1000 * 3, new InvokeCallback() { @Override public void operationComplete(ResponseFuture responseFuture) { System.out.println(responseFuture.getResponseCommand()); @@ -124,7 +127,7 @@ public void test_server_call_client() throws InterruptedException, RemotingConne final RemotingServer server = createRemotingServer(); final RemotingClient client = createRemotingClient(); - server.registerProcessor(RequestCode.DEMO_REQUEST_VALUE, new NettyRequestProcessor() { + server.registerProcessor(0, new NettyRequestProcessor() { @Override public RemotingCommand processRequest(ChannelHandlerContext ctx, RemotingCommand request) { try { @@ -144,7 +147,7 @@ public RemotingCommand processRequest(ChannelHandlerContext ctx, RemotingCommand } }, Executors.newCachedThreadPool()); - client.registerProcessor(RequestCode.DEMO_REQUEST_VALUE, new NettyRequestProcessor() { + client.registerProcessor(0, new NettyRequestProcessor() { @Override public RemotingCommand processRequest(ChannelHandlerContext ctx, RemotingCommand request) { System.out.println("client receive server request = " + request); @@ -154,8 +157,8 @@ public RemotingCommand processRequest(ChannelHandlerContext ctx, RemotingCommand }, Executors.newCachedThreadPool()); for (int i = 0; i < 3; i++) { - RemotingCommand request = RemotingCommand.createRequestCommand(RequestCode.DEMO_REQUEST_VALUE, null); - RemotingCommand response = client.invokeSync("127.0.0.1:10911", request, 1000 * 3); + RemotingCommand request = RemotingCommand.createRequestCommand(0, null); + RemotingCommand response = client.invokeSync("127.0.0.1:8888", request, 1000 * 3); System.out.println("invoke result = " + response); assertTrue(response != null); } @@ -164,4 +167,74 @@ public RemotingCommand processRequest(ChannelHandlerContext ctx, RemotingCommand server.shutdown(); System.out.println("-----------------------------------------------------------------"); } + +} + + +class TestRequestHeader implements CommandCustomHeader { + @CFNullable + private Integer count; + + @CFNullable + private String messageTitle; + + + @Override + public void checkFields() throws RemotingCommandException { + } + + + public Integer getCount() { + return count; + } + + + public void setCount(Integer count) { + this.count = count; + } + + + public String getMessageTitle() { + return messageTitle; + } + + + public void setMessageTitle(String messageTitle) { + this.messageTitle = messageTitle; + } +} + + +class TestResponseHeader implements CommandCustomHeader { + @CFNullable + private Integer count; + + @CFNullable + private String messageTitle; + + + @Override + public void checkFields() throws RemotingCommandException { + + } + + + public Integer getCount() { + return count; + } + + + public void setCount(Integer count) { + this.count = count; + } + + + public String getMessageTitle() { + return messageTitle; + } + + + public void setMessageTitle(String messageTitle) { + this.messageTitle = messageTitle; + } } diff --git a/rocketmq-remoting/src/test/java/com/alibaba/rocketmq/remoting/SyncInvokeTest.java b/rocketmq-remoting/src/test/java/com/alibaba/rocketmq/remoting/SyncInvokeTest.java index 7c8d3fa4..2287c7d8 100644 --- a/rocketmq-remoting/src/test/java/com/alibaba/rocketmq/remoting/SyncInvokeTest.java +++ b/rocketmq-remoting/src/test/java/com/alibaba/rocketmq/remoting/SyncInvokeTest.java @@ -8,12 +8,10 @@ import org.junit.Test; import com.alibaba.rocketmq.remoting.protocol.RemotingCommand; -import com.alibaba.rocketmq.remoting.protocol.RemotingProtos.RequestCode; /** - * @author vintage.wang@gmail.com shijia.wxr@taobao.com - * + * @author shijia.wxr */ public class SyncInvokeTest { @Test @@ -23,7 +21,7 @@ public void test_RPC_Sync() throws Exception { for (int i = 0; i < 1000000; i++) { try { - RemotingCommand request = RemotingCommand.createRequestCommand(RequestCode.DEMO_REQUEST_VALUE, null); + RemotingCommand request = RemotingCommand.createRequestCommand(0, null); RemotingCommand response = client.invokeSync("127.0.0.1:10911", request, 1000 * 3); System.out.println(i + "\t" + "invoke result = " + response); assertTrue(response != null); diff --git a/rocketmq-remoting/src/test/java/com/alibaba/rocketmq/subclass/TestSubClassAuto.java b/rocketmq-remoting/src/test/java/com/alibaba/rocketmq/subclass/TestSubClassAuto.java index dc00a281..a6ef2e2d 100644 --- a/rocketmq-remoting/src/test/java/com/alibaba/rocketmq/subclass/TestSubClassAuto.java +++ b/rocketmq-remoting/src/test/java/com/alibaba/rocketmq/subclass/TestSubClassAuto.java @@ -1,16 +1,13 @@ /** - * + * */ package com.alibaba.rocketmq.subclass; import org.junit.Test; -import com.alibaba.rocketmq.remoting.CommandCustomHeader; - /** - * @author vintage.wang@gmail.com shijia.wxr@taobao.com - * + * @author shijia.wxr */ public class TestSubClassAuto { @Test diff --git a/rocketmq-research/pom.xml b/rocketmq-research/pom.xml index 1fb5c845..05f288c3 100644 --- a/rocketmq-research/pom.xml +++ b/rocketmq-research/pom.xml @@ -1,14 +1,12 @@ - + com.alibaba.rocketmq rocketmq-all - 3.0.0-SNAPSHOT + 3.0.8-SNAPSHOT 4.0.0 jar - com.alibaba.rocketmq rocketmq-research rocketmq-research ${project.version} @@ -26,13 +24,21 @@ ${project.groupId} rocketmq-store + + ${project.groupId} + rocketmq-client + io.netty netty-all - - ch.qos.logback - logback-classic - + + ch.qos.logback + logback-classic + + + com.alibaba + fastjson + diff --git a/rocketmq-research/src/main/java/com/alibaba/rocketmq/research/Test.java b/rocketmq-research/src/main/java/com/alibaba/rocketmq/research/Test.java new file mode 100644 index 00000000..8d6d9065 --- /dev/null +++ b/rocketmq-research/src/main/java/com/alibaba/rocketmq/research/Test.java @@ -0,0 +1,49 @@ +package com.alibaba.rocketmq.research; + +import java.util.Calendar; + +import com.alibaba.rocketmq.common.UtilAll; + + +/** + * @author shijia.wxr + */ +public class Test { + + public static long computNextMorningTimeMillis() { + Calendar cal = Calendar.getInstance(); + cal.set(Calendar.YEAR, 2013); + cal.set(Calendar.MONTH, 10); + cal.set(Calendar.DAY_OF_MONTH, 11); + cal.set(Calendar.HOUR_OF_DAY, 0); + cal.set(Calendar.MINUTE, 0); + cal.set(Calendar.SECOND, 0); + cal.set(Calendar.MILLISECOND, 0); + return cal.getTimeInMillis(); + } + + + private static String diskUtil() { + String storePathPhysic = System.getenv("HOME"); + double physicRatio = UtilAll.getDiskPartitionSpaceUsedPercent(storePathPhysic); + + String storePathLogis = storePathPhysic; + double logisRatio = UtilAll.getDiskPartitionSpaceUsedPercent(storePathLogis); + + String storePathIndex = storePathPhysic; + double indexRatio = UtilAll.getDiskPartitionSpaceUsedPercent(storePathIndex); + + return String.format("CL: %5.2f CQ: %5.2f INDEX: %5.2f", physicRatio, logisRatio, indexRatio); + } + + + public static void main(String[] args) { + int a = -25; + int b = 1; + + int c = a % b; + System.out.println(c); + + System.out.println(diskUtil()); + } +} diff --git a/rocketmq-research/src/main/java/com/alibaba/rocketmq/research/client/ClientConfigTest.java b/rocketmq-research/src/main/java/com/alibaba/rocketmq/research/client/ClientConfigTest.java new file mode 100644 index 00000000..54bc7e13 --- /dev/null +++ b/rocketmq-research/src/main/java/com/alibaba/rocketmq/research/client/ClientConfigTest.java @@ -0,0 +1,40 @@ +/** + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.rocketmq.research.client; + +import java.net.SocketException; + +import com.alibaba.rocketmq.client.ClientConfig; +import com.alibaba.rocketmq.client.consumer.DefaultMQPullConsumer; +import com.alibaba.rocketmq.client.consumer.DefaultMQPushConsumer; +import com.alibaba.rocketmq.client.producer.DefaultMQProducer; +import com.alibaba.rocketmq.client.producer.TransactionMQProducer; +import com.alibaba.rocketmq.common.MixAll; + + +public class ClientConfigTest { + public static void main(String[] args) throws SocketException { + MixAll.printObjectProperties(null, new ClientConfig()); + System.out.println("----------------------------------------------"); + MixAll.printObjectProperties(null, new DefaultMQProducer()); + System.out.println("----------------------------------------------"); + MixAll.printObjectProperties(null, new TransactionMQProducer()); + System.out.println("----------------------------------------------"); + MixAll.printObjectProperties(null, new DefaultMQPushConsumer()); + System.out.println("----------------------------------------------"); + MixAll.printObjectProperties(null, new DefaultMQPullConsumer()); + } +} diff --git a/rocketmq-research/src/main/java/com/alibaba/rocketmq/research/fastjson/Test.java b/rocketmq-research/src/main/java/com/alibaba/rocketmq/research/fastjson/Test.java new file mode 100644 index 00000000..e88a3dc8 --- /dev/null +++ b/rocketmq-research/src/main/java/com/alibaba/rocketmq/research/fastjson/Test.java @@ -0,0 +1,54 @@ +package com.alibaba.rocketmq.research.fastjson; + +import java.util.concurrent.ConcurrentHashMap; + +import com.alibaba.fastjson.JSON; +import com.alibaba.rocketmq.remoting.protocol.RemotingSerializable; + + +/** + * @author shijia.wxr + * @since 2013-6-18 + */ +public class Test { + + public static class TestTable { + private final ConcurrentHashMap> testTable = + new ConcurrentHashMap>(); + private String remark = "abc"; + + + public ConcurrentHashMap> getTestTable() { + return testTable; + } + + + public String getRemark() { + return remark; + } + + + public void setRemark(String remark) { + this.remark = remark; + } + } + + + public static void main(String[] args) { + TestTable testTable = new TestTable(); + testTable.getTestTable().put("consumer1", new ConcurrentHashMap()); + testTable.getTestTable().put("consumer2", new ConcurrentHashMap()); + testTable.getTestTable().put("consumer3", new ConcurrentHashMap()); + + testTable.getTestTable().get("consumer1").put("A", 100L); + testTable.getTestTable().get("consumer1").put("B", 200L); + testTable.getTestTable().get("consumer1").put("C", 300L); + + String jsonString = RemotingSerializable.toJson(testTable, true); + + String jsonStringFmt = JSON.toJSONString(testTable, true); + + System.out.println(jsonString); + System.out.println(jsonStringFmt); + } +} diff --git a/rocketmq-research/src/main/java/com/alibaba/rocketmq/research/gson/Contact.java b/rocketmq-research/src/main/java/com/alibaba/rocketmq/research/gson/Contact.java new file mode 100644 index 00000000..3c24a70f --- /dev/null +++ b/rocketmq-research/src/main/java/com/alibaba/rocketmq/research/gson/Contact.java @@ -0,0 +1,81 @@ +package com.alibaba.rocketmq.research.gson; + +public class Contact { + public final static String SUB_ALL = "*"; + private String name; + private int age; + private double weight; + private String school; + private SexType sex; + + + public String getName() { + return name; + } + + + public void setName(String name) { + this.name = name; + } + + + public int getAge() { + return age; + } + + + public void setAge(int age) { + this.age = age; + } + + + public double getWeight() { + return weight; + } + + + public void setWeight(double weight) { + this.weight = weight; + } + + + public String getSchool() { + return school; + } + + + public void setSchool(String school) { + this.school = school; + } + + + public SexType getSex() { + return sex; + } + + + public void setSex(SexType sex) { + this.sex = sex; + } + + + public Contact() { + } + + + public Contact(String name, int age, double weight, String school, SexType sex) { + super(); + this.name = name; + this.age = age; + this.weight = weight; + this.school = school; + this.sex = sex; + } + + + @Override + public String toString() { + return "Contact [name=" + name + ", age=" + age + ", weight=" + weight + ", school=" + school + + ", sex=" + sex + "]"; + } +} diff --git a/rocketmq-research/src/main/java/com/alibaba/rocketmq/research/gson/ContactBook.java b/rocketmq-research/src/main/java/com/alibaba/rocketmq/research/gson/ContactBook.java new file mode 100644 index 00000000..2394c14d --- /dev/null +++ b/rocketmq-research/src/main/java/com/alibaba/rocketmq/research/gson/ContactBook.java @@ -0,0 +1,62 @@ +package com.alibaba.rocketmq.research.gson; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + + +public class ContactBook extends Convert { + private String name; + private List contactList = new ArrayList(); + private Map customField = new HashMap(); + + private int code; + + + public String getName() { + return name; + } + + + public void setName(String name) { + this.name = name; + } + + + public List getContactList() { + return contactList; + } + + + public void setContactList(List contactList) { + this.contactList = contactList; + } + + + public int getCode() { + return code; + } + + + public void setCode(int code) { + this.code = code; + } + + + public Map getCustomField() { + return customField; + } + + + public void setCustomField(Map customField) { + this.customField = customField; + } + + + @Override + public String toString() { + return "ContactBook [name=" + name + ", contactList=" + contactList + ", customField=" + customField + + ", code=" + code + "]"; + } +} diff --git a/rocketmq-research/src/main/java/com/alibaba/rocketmq/research/gson/Convert.java b/rocketmq-research/src/main/java/com/alibaba/rocketmq/research/gson/Convert.java new file mode 100644 index 00000000..1abe4526 --- /dev/null +++ b/rocketmq-research/src/main/java/com/alibaba/rocketmq/research/gson/Convert.java @@ -0,0 +1,22 @@ +/** + * + */ +package com.alibaba.rocketmq.research.gson; + +/** + * @author shijia.wxr + */ +public abstract class Convert { + // public String encode() { + // GsonBuilder builder = new GsonBuilder(); + // Gson gson = builder.create(); + // return gson.toJson(this); + // } + // + // + // public static T decode(String json, Class classOfT) { + // GsonBuilder builder = new GsonBuilder(); + // Gson gson = builder.create(); + // return gson.fromJson(json, classOfT); + // } +} diff --git a/rocketmq-research/src/main/java/com/alibaba/rocketmq/research/gson/SexType.java b/rocketmq-research/src/main/java/com/alibaba/rocketmq/research/gson/SexType.java new file mode 100644 index 00000000..39044e86 --- /dev/null +++ b/rocketmq-research/src/main/java/com/alibaba/rocketmq/research/gson/SexType.java @@ -0,0 +1,6 @@ +package com.alibaba.rocketmq.research.gson; + +public enum SexType { + BOY, + GIRL +} diff --git a/rocketmq-research/src/main/java/com/alibaba/rocketmq/research/gson/TestConvert.java b/rocketmq-research/src/main/java/com/alibaba/rocketmq/research/gson/TestConvert.java new file mode 100644 index 00000000..0440e71a --- /dev/null +++ b/rocketmq-research/src/main/java/com/alibaba/rocketmq/research/gson/TestConvert.java @@ -0,0 +1,27 @@ +/** + * + */ +package com.alibaba.rocketmq.research.gson; + +/** + * @author shijia.wxr + */ +public class TestConvert { + + public static void main(String[] args) { + ContactBook contactBook = new ContactBook(); + + contactBook.setName("张三的通信录"); + contactBook.setCode(100); + + contactBook.getContactList().add(new Contact("刘德华", 54, 60.56, "本科", SexType.BOY)); + contactBook.getContactList().add(new Contact("张惠妹", 41, 52.69, "研究生", SexType.GIRL)); + contactBook.getContactList().add(new Contact("周星驰", 54, 61.22, "博士", SexType.BOY)); + + // String json = contactBook.encode(); + // System.out.println(json); + // + // ContactBook d = ContactBook.decode(json, ContactBook.class); + // System.out.println(d); + } +} diff --git a/rocketmq-research/src/main/java/com/alibaba/rocketmq/research/gson/TestFastjson.java b/rocketmq-research/src/main/java/com/alibaba/rocketmq/research/gson/TestFastjson.java new file mode 100644 index 00000000..a3ae5608 --- /dev/null +++ b/rocketmq-research/src/main/java/com/alibaba/rocketmq/research/gson/TestFastjson.java @@ -0,0 +1,30 @@ +package com.alibaba.rocketmq.research.gson; + +//import com.alibaba.fastjson.JSON; +//import com.alibaba.fastjson.serializer.SerializerFeature; + +/** + * @author shijia.wxr + */ +public class TestFastjson { + + public static void main(String[] args) { + ContactBook contactBook = new ContactBook(); + + contactBook.setName("张三的通信录"); + contactBook.setCode(100); + + contactBook.getContactList().add(new Contact("刘德华", 54, 60.56, "本科\"", SexType.BOY)); + contactBook.getContactList().add(new Contact("张惠妹", 41, 52.69, "研究生", SexType.GIRL)); + contactBook.getContactList().add(new Contact("周星驰", 54, 61.22, "博士", SexType.BOY)); + + // String json = JSON.toJSONString(contactBook, + // SerializerFeature.WriteClassName); + // System.out.println(json); + + // ContactBook fan = (ContactBook) JSON.parse(json); + + // ContactBook fan = JSON.parseObject(json, ContactBook.class); + // System.out.println(fan); + } +} diff --git a/rocketmq-research/src/main/java/com/alibaba/rocketmq/research/gson/TestGson.java b/rocketmq-research/src/main/java/com/alibaba/rocketmq/research/gson/TestGson.java new file mode 100644 index 00000000..486c9b5e --- /dev/null +++ b/rocketmq-research/src/main/java/com/alibaba/rocketmq/research/gson/TestGson.java @@ -0,0 +1,40 @@ +package com.alibaba.rocketmq.research.gson; + +//import com.google.gson.Gson; +//import com.google.gson.GsonBuilder; +// +// +///** +// * @author shijia.wxr +// */ +//public class TestGson { +// +// public static void main(String[] args) { +// ContactBook contactBook = new ContactBook(); +// +// contactBook.setName("张三的通信录"); +// contactBook.setCode(100); +// +// contactBook.getCustomField().put(new Contact("刘德华", 54, 60.56, "本科\"", SexType.BOY), "CustomValue1"); +// contactBook.getCustomField().put(new Contact("张惠妹", 41, 52.69, "研究生", SexType.GIRL), "CustomValue2"); +// contactBook.getCustomField().put(new Contact("周星驰", 54, 61.22, "博士", SexType.BOY), "CustomValue3"); +// +// contactBook.getContactList().add(new Contact("刘德华", 54, 60.56, "本科\"", SexType.BOY)); +// contactBook.getContactList().add(new Contact("张惠妹", 41, 52.69, "研究生", SexType.GIRL)); +// contactBook.getContactList().add(new Contact("周星驰", 54, 61.22, "博士", SexType.BOY)); +// +// GsonBuilder builder = new GsonBuilder(); +// // // builder.excludeFieldsWithoutExposeAnnotation(); +// // +// Gson gson = builder.create(); +// +// String json = gson.toJson(contactBook); +// System.out.println(json); +// +// ContactBook cb = gson.fromJson(json, ContactBook.class); +// System.out.println(cb); +// String json2 = gson.toJson(cb); +// System.out.println(json2); +// +// } +// } diff --git a/rocketmq-research/src/main/java/com/alibaba/rocketmq/research/logback/LogbackTest.java b/rocketmq-research/src/main/java/com/alibaba/rocketmq/research/logback/LogbackTest.java index 8cbf044f..4da2a383 100644 --- a/rocketmq-research/src/main/java/com/alibaba/rocketmq/research/logback/LogbackTest.java +++ b/rocketmq-research/src/main/java/com/alibaba/rocketmq/research/logback/LogbackTest.java @@ -8,8 +8,7 @@ /** - * @author vintage.wang@gmail.com shijia.wxr@taobao.com - * + * @author shijia.wxr */ public class LogbackTest { public final static Logger log = LoggerFactory.getLogger(LogbackTest.class); diff --git a/rocketmq-research/src/main/java/com/alibaba/rocketmq/research/mix/Test1.java b/rocketmq-research/src/main/java/com/alibaba/rocketmq/research/mix/Test1.java index 0c389fa7..efe11aa5 100644 --- a/rocketmq-research/src/main/java/com/alibaba/rocketmq/research/mix/Test1.java +++ b/rocketmq-research/src/main/java/com/alibaba/rocketmq/research/mix/Test1.java @@ -4,49 +4,19 @@ package com.alibaba.rocketmq.research.mix; /** - * @author vintage.wang@gmail.com shijia.wxr@taobao.com - * + * @author shijia.wxr */ public class Test1 { - private int a = 10; - - - public static void main(String[] args) throws InstantiationException, IllegalAccessException { - // String processName = - // java.lang.management.ManagementFactory.getRuntimeMXBean().getName(); - // - // String processID = processName.substring(0, - // processName.indexOf('@')); - // - // System.out.println("processID=" + processID); - - -// int i = 0; -// -// Integer abc = 99; -// i = abc; -// System.out.println(abc); - - long i = 100L; - Object obj = i; - System.out.println(obj); - System.out.println(obj.getClass()); - - Test1 test1 = Test1.class.newInstance(); - - test1.register(Test1.class); - System.out.println(test1); - } - - - public void register(Class t) { + public static void test_1(String[] args) { + long timeLong = System.currentTimeMillis(); + System.out.println(" timeLong = " + timeLong); + int timeInt = (int) (timeLong / 1000); + System.out.println(" timeInt = " + timeInt); } - @Override - public String toString() { - return "Test1 [a=" + a + "]"; + public static void main(String[] args) { + test_1(args); } - } diff --git a/rocketmq-research/src/main/java/com/alibaba/rocketmq/research/rpc/Connection.java b/rocketmq-research/src/main/java/com/alibaba/rocketmq/research/rpc/Connection.java index d9e7f06c..25354d7e 100644 --- a/rocketmq-research/src/main/java/com/alibaba/rocketmq/research/rpc/Connection.java +++ b/rocketmq-research/src/main/java/com/alibaba/rocketmq/research/rpc/Connection.java @@ -18,9 +18,9 @@ /** - * һSocketӶClientServerͨ + * 一个Socket连接对象,Client与Server通用 * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * @author shijia.wxr */ public class Connection { private static final int ReadMaxBufferSize = 1024 * 1024 * 4; @@ -202,9 +202,9 @@ public void shutdown() { /** - * select¼ + * 处理select读事件 * - * @return ش + * @return 返回处理结果 */ public boolean processReadEvent() { int readSizeZeroTimes = 0; @@ -238,16 +238,16 @@ else if (readSize == 0) { private void dispatchReadRequest() { int writePostion = this.byteBufferRead.position(); - // ̳߳Ż + // 针对线程池优化 final List requestList = new LinkedList(); while (true) { int diff = this.byteBufferRead.position() - this.dispatchPostion; if (diff >= 8) { - // msgSizeϢreqId + // msgSize不包含消息reqId int msgSize = this.byteBufferRead.getInt(this.dispatchPostion); final Integer reqId = this.byteBufferRead.getInt(this.dispatchPostion + 4); - // Դչһ + // 可以凑够一个请求 if (diff >= (8 + msgSize)) { this.byteBufferRead.position(0); final ByteBuffer request = this.byteBufferRead.slice(); @@ -296,9 +296,9 @@ public void run() { continue; } - // ޷չһ + // 无法凑够一个请求 else { - // ByteBufferˣµڴ + // ByteBuffer满了,分配新的内存 if (!this.byteBufferRead.hasRemaining()) { this.reallocateByteBuffer(); } @@ -313,7 +313,7 @@ else if (!this.byteBufferRead.hasRemaining()) { break; } - // һ߳ж + // 一个线程内运行多个任务 for (boolean retry = true; retry;) { try { if (!requestList.isEmpty()) { @@ -323,7 +323,8 @@ public void run() { for (ByteBuffer request : requestList) { try { final int reqId = request.getInt(request.position() - 4); - byte[] response = Connection.this.rpcServerProcessor.process(reqId, request); + byte[] response = + Connection.this.rpcServerProcessor.process(reqId, request); if (response != null) { Connection.this.linkeByteBufferList.putData(reqId, response); } diff --git a/rocketmq-research/src/main/java/com/alibaba/rocketmq/research/rpc/DefaultRPCClient.java b/rocketmq-research/src/main/java/com/alibaba/rocketmq/research/rpc/DefaultRPCClient.java index a326bc9a..640c3e00 100644 --- a/rocketmq-research/src/main/java/com/alibaba/rocketmq/research/rpc/DefaultRPCClient.java +++ b/rocketmq-research/src/main/java/com/alibaba/rocketmq/research/rpc/DefaultRPCClient.java @@ -16,9 +16,9 @@ /** - * ͻʵ + * 客户端实现 * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * @author shijia.wxr */ public class DefaultRPCClient implements RPCClient { // private Connection connection; diff --git a/rocketmq-research/src/main/java/com/alibaba/rocketmq/research/rpc/DefaultRPCServer.java b/rocketmq-research/src/main/java/com/alibaba/rocketmq/research/rpc/DefaultRPCServer.java index 7830879c..9f027d6a 100644 --- a/rocketmq-research/src/main/java/com/alibaba/rocketmq/research/rpc/DefaultRPCServer.java +++ b/rocketmq-research/src/main/java/com/alibaba/rocketmq/research/rpc/DefaultRPCServer.java @@ -24,9 +24,9 @@ /** - * ʵ + * 服务端实现 * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * @author shijia.wxr */ public class DefaultRPCServer implements RPCServer { private final int listenPort; @@ -54,7 +54,8 @@ public void run() { for (SelectionKey k : selectedList) { if ((k.readyOps() & SelectionKey.OP_ACCEPT) != 0) { SocketChannel sc = ((ServerSocketChannel) k.channel()).accept(); - System.out.println("receive new connection, " + sc.socket().getRemoteSocketAddress()); + System.out.println("receive new connection, " + + sc.socket().getRemoteSocketAddress()); Connection newConnection = new Connection(sc, DefaultRPCServer.this.rpcServerProcessor, DefaultRPCServer.this.executor); @@ -71,7 +72,7 @@ public void run() { DefaultRPCServer.this.connectionList.add(newConnection); newConnection.start(); } - // TODO CLOSE SOCKET + // TODO, CLOSE SOCKET else { System.out.println("Unexpected ops in select " + k.readyOps()); } @@ -96,7 +97,8 @@ public String getServiceName() { } - public DefaultRPCServer(final int listenPort, final int minPoolSize, final int maxPoolSize) throws IOException { + public DefaultRPCServer(final int listenPort, final int minPoolSize, final int maxPoolSize) + throws IOException { this.listenPort = listenPort; this.socketAddressListen = new InetSocketAddress(this.listenPort); this.serverSocketChannel = ServerSocketChannel.open(); diff --git a/rocketmq-research/src/main/java/com/alibaba/rocketmq/research/rpc/LinkedByteBufferList.java b/rocketmq-research/src/main/java/com/alibaba/rocketmq/research/rpc/LinkedByteBufferList.java index 0a993970..6e28fe26 100644 --- a/rocketmq-research/src/main/java/com/alibaba/rocketmq/research/rpc/LinkedByteBufferList.java +++ b/rocketmq-research/src/main/java/com/alibaba/rocketmq/research/rpc/LinkedByteBufferList.java @@ -9,9 +9,9 @@ /** - * дŻByteBuffer + * 针对写优化的ByteBuffer序列 * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * @author shijia.wxr */ public class LinkedByteBufferList { class ByteBufferNode { @@ -97,7 +97,7 @@ public AtomicInteger getWriteOffset() { private final LinkedBlockingDeque bbnIdleList = new LinkedBlockingDeque(); - // ǷѾNotify + // 是否已经被Notify过 protected volatile boolean hasNotified = false; @@ -107,7 +107,7 @@ public LinkedByteBufferList() { } - // TODO Ҫ + // TODO 可能需要流控 public void putData(final int reqId, final byte[] data) { final int HEADER_SIZE = 8; ByteBuffer header = ByteBuffer.allocate(HEADER_SIZE); @@ -117,12 +117,12 @@ public void putData(final int reqId, final byte[] data) { synchronized (this) { int minHeader = Math.min(HEADER_SIZE, this.currentWriteNode.getByteBufferWrite().remaining()); int minData = 0; - // дͷ + // 尝试写入头 if (minHeader > 0) { this.currentWriteNode.getByteBufferWrite().put(header.array(), 0, minHeader); this.currentWriteNode.getWriteOffset().addAndGet(minHeader); } - // д + // 尝试写入体 if (minHeader == HEADER_SIZE) { minData = Math.min(data.length, this.currentWriteNode.getByteBufferWrite().remaining()); if (minData > 0) { @@ -131,10 +131,10 @@ public void putData(final int reqId, final byte[] data) { } } - // ҪµBuffer + // 需要创建新的Buffer if (!this.currentWriteNode.getByteBufferWrite().hasRemaining()) { ByteBufferNode newNode = null; - // Դӿдȡ + // 尝试从空闲处取 newNode = this.bbnIdleList.poll(); if (null == newNode) { newNode = new ByteBufferNode(); @@ -143,15 +143,16 @@ public void putData(final int reqId, final byte[] data) { this.currentWriteNode.setNextByteBufferNode(newNode.clearAndReturnNew()); this.currentWriteNode = newNode; - // Header + // 补偿Header int remainHeaderPut = HEADER_SIZE - minHeader; int remainDataPut = data.length - minData; if (remainHeaderPut > 0) { - this.currentWriteNode.getByteBufferWrite().put(header.array(), minHeader, remainHeaderPut); + this.currentWriteNode.getByteBufferWrite() + .put(header.array(), minHeader, remainHeaderPut); this.currentWriteNode.getWriteOffset().addAndGet(remainHeaderPut); } - // Data + // 补偿Data if (remainDataPut > 0) { this.currentWriteNode.getByteBufferWrite().put(data, minData, remainDataPut); this.currentWriteNode.getWriteOffset().addAndGet(remainDataPut); diff --git a/rocketmq-research/src/main/java/com/alibaba/rocketmq/research/rpc/RPCClient.java b/rocketmq-research/src/main/java/com/alibaba/rocketmq/research/rpc/RPCClient.java index edf6ec5f..fa47d6f5 100644 --- a/rocketmq-research/src/main/java/com/alibaba/rocketmq/research/rpc/RPCClient.java +++ b/rocketmq-research/src/main/java/com/alibaba/rocketmq/research/rpc/RPCClient.java @@ -8,9 +8,9 @@ /** - * ͻ˽ӿ + * 客户端接口 * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * @author shijia.wxr */ public interface RPCClient { public void start(); diff --git a/rocketmq-research/src/main/java/com/alibaba/rocketmq/research/rpc/RPCProcessor.java b/rocketmq-research/src/main/java/com/alibaba/rocketmq/research/rpc/RPCProcessor.java index 386ec3e8..ef0a1587 100644 --- a/rocketmq-research/src/main/java/com/alibaba/rocketmq/research/rpc/RPCProcessor.java +++ b/rocketmq-research/src/main/java/com/alibaba/rocketmq/research/rpc/RPCProcessor.java @@ -7,9 +7,9 @@ /** - * ServerClientͼ + * Server与Client的读事件处理 * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * @author vintage.wang@gmail.com shijia.wxr@taobao.com */ public interface RPCProcessor { public byte[] process(final int upId, final ByteBuffer upstream); diff --git a/rocketmq-research/src/main/java/com/alibaba/rocketmq/research/rpc/RPCServer.java b/rocketmq-research/src/main/java/com/alibaba/rocketmq/research/rpc/RPCServer.java index 1b09a4e4..e282089d 100644 --- a/rocketmq-research/src/main/java/com/alibaba/rocketmq/research/rpc/RPCServer.java +++ b/rocketmq-research/src/main/java/com/alibaba/rocketmq/research/rpc/RPCServer.java @@ -4,9 +4,9 @@ package com.alibaba.rocketmq.research.rpc; /** - * һRPC Server + * 一个简单RPC Server * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * @author vintage.wang@gmail.com shijia.wxr@taobao.com */ public interface RPCServer { public void start(); diff --git a/rocketmq-research/src/main/java/com/alibaba/rocketmq/research/rpc/benchmark/Client.java b/rocketmq-research/src/main/java/com/alibaba/rocketmq/research/rpc/benchmark/Client.java index adc2ae9f..03783812 100644 --- a/rocketmq-research/src/main/java/com/alibaba/rocketmq/research/rpc/benchmark/Client.java +++ b/rocketmq-research/src/main/java/com/alibaba/rocketmq/research/rpc/benchmark/Client.java @@ -11,9 +11,9 @@ /** - * 򵥹ܲԣClient + * 简单功能测试,Client端 * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * @author shijia.wxr */ public class Client { public static void main(String[] args) { @@ -28,7 +28,8 @@ public static void main(String[] args) { ByteBuffer repdata = rpcClient.call(reqstr.getBytes()); if (repdata != null) { String repstr = - new String(repdata.array(), repdata.position(), repdata.limit() - repdata.position()); + new String(repdata.array(), repdata.position(), repdata.limit() + - repdata.position()); System.out.println("call result, " + repstr); } else { diff --git a/rocketmq-research/src/main/java/com/alibaba/rocketmq/research/rpc/benchmark/MTClient.java b/rocketmq-research/src/main/java/com/alibaba/rocketmq/research/rpc/benchmark/MTClient.java index 15eeb385..5a804f48 100644 --- a/rocketmq-research/src/main/java/com/alibaba/rocketmq/research/rpc/benchmark/MTClient.java +++ b/rocketmq-research/src/main/java/com/alibaba/rocketmq/research/rpc/benchmark/MTClient.java @@ -14,9 +14,9 @@ /** - * ߳̿ͻˣѹ + * 多线程客户端,做性能压测 * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * @author shijia.wxr */ public class MTClient { private static byte[] buildMessage(final int size) { @@ -32,7 +32,8 @@ private static byte[] buildMessage(final int size) { public static void main(String[] args) { if (args.length < 2) { - System.err.println("Useage: mtclient remoteHost remotePort [messageSize] [threadCnt] [connectionCnt]"); + System.err + .println("Useage: mtclient remoteHost remotePort [messageSize] [threadCnt] [connectionCnt]"); return; } @@ -48,7 +49,8 @@ public static void main(String[] args) { // rpcclient final RPCClient rpcClient = new DefaultRPCClient(); - final boolean connectOK = rpcClient.connect(new InetSocketAddress(remoteHost, remotePort), connectionCnt); + final boolean connectOK = + rpcClient.connect(new InetSocketAddress(remoteHost, remotePort), connectionCnt); System.out.println("connect server " + remoteHost + (connectOK ? " OK" : " Failed")); rpcClient.start(); diff --git a/rocketmq-research/src/main/java/com/alibaba/rocketmq/research/rpc/benchmark/Server.java b/rocketmq-research/src/main/java/com/alibaba/rocketmq/research/rpc/benchmark/Server.java index 868717fe..6b44c5f1 100644 --- a/rocketmq-research/src/main/java/com/alibaba/rocketmq/research/rpc/benchmark/Server.java +++ b/rocketmq-research/src/main/java/com/alibaba/rocketmq/research/rpc/benchmark/Server.java @@ -13,9 +13,9 @@ /** - * 򵥹ܲԣServer + * 简单功能测试,Server端 * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * @author shijia.wxr */ public class Server { static class ServerRPCProcessor implements RPCProcessor { diff --git a/rocketmq-research/src/main/java/com/alibaba/rocketmq/research/store/MessageStoreTestObject.java b/rocketmq-research/src/main/java/com/alibaba/rocketmq/research/store/MessageStoreTestObject.java index cfa3d651..cf2085c1 100644 --- a/rocketmq-research/src/main/java/com/alibaba/rocketmq/research/store/MessageStoreTestObject.java +++ b/rocketmq-research/src/main/java/com/alibaba/rocketmq/research/store/MessageStoreTestObject.java @@ -14,23 +14,22 @@ /** - * Դ洢㣬򵥷װ - * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * 测试存储层,简单封装 * + * @author shijia.wxr */ public class MessageStoreTestObject { - // ϢС + // 消息大小 protected int MessageSize = 1024 * 2; - // и + // 队列个数 protected int QUEUE_TOTAL = 1024; - // ĸ + // 发往哪个队列 protected AtomicInteger queueId = new AtomicInteger(0); - // ַ + // 发送主机地址 protected SocketAddress bornHost; - // 洢ַ + // 存储主机地址 protected SocketAddress storeHost; - // Ϣ + // 消息体 protected byte[] messageBody; // @@ -86,7 +85,7 @@ public boolean sendMessage() { public void updateMasterAddress(final String addr) { - this.messageStore.updateMasterAddress(addr); + this.messageStore.updateHaMasterAddress(addr); } diff --git a/rocketmq-research/src/main/java/com/alibaba/rocketmq/research/storeha/BrokerMaster.java b/rocketmq-research/src/main/java/com/alibaba/rocketmq/research/storeha/BrokerMaster.java index b02cc892..05851cac 100644 --- a/rocketmq-research/src/main/java/com/alibaba/rocketmq/research/storeha/BrokerMaster.java +++ b/rocketmq-research/src/main/java/com/alibaba/rocketmq/research/storeha/BrokerMaster.java @@ -12,10 +12,9 @@ /** - * HA - * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * HA测试 * + * @author shijia.wxr */ public class BrokerMaster { @@ -41,7 +40,8 @@ public static void main(String[] args) { System.out.println("wait over"); // Thread pool - final ThreadPoolExecutor executorSend = (ThreadPoolExecutor) Executors.newFixedThreadPool(ThreadSize); + final ThreadPoolExecutor executorSend = + (ThreadPoolExecutor) Executors.newFixedThreadPool(ThreadSize); final AtomicLong maxResponseTime = new AtomicLong(0); final AtomicLong sendTotalCnt = new AtomicLong(0); diff --git a/rocketmq-research/src/main/java/com/alibaba/rocketmq/research/storeha/BrokerSlave.java b/rocketmq-research/src/main/java/com/alibaba/rocketmq/research/storeha/BrokerSlave.java index 3cced51a..437028b0 100644 --- a/rocketmq-research/src/main/java/com/alibaba/rocketmq/research/storeha/BrokerSlave.java +++ b/rocketmq-research/src/main/java/com/alibaba/rocketmq/research/storeha/BrokerSlave.java @@ -9,10 +9,9 @@ /** - * HA - * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * HA测试 * + * @author shijia.wxr */ public class BrokerSlave { diff --git a/rocketmq-research/src/main/java/com/alibaba/rocketmq/research/udp/UDPTest.java b/rocketmq-research/src/main/java/com/alibaba/rocketmq/research/udp/UDPTest.java new file mode 100644 index 00000000..517e8852 --- /dev/null +++ b/rocketmq-research/src/main/java/com/alibaba/rocketmq/research/udp/UDPTest.java @@ -0,0 +1,19 @@ +package com.alibaba.rocketmq.research.udp; + +import java.net.DatagramSocket; +import java.net.SocketException; + + +/** + * @author shijia.wxr + */ +public class UDPTest { + + public static void main(String[] args) throws SocketException { + DatagramSocket datagramSocket = new DatagramSocket(4500); + System.out.println("OK 4500"); + + new DatagramSocket(4500); + System.out.println("OK 4500"); + } +} diff --git a/rocketmq-research/src/test/java/com/alibaba/research/fastjson/TestEqual.java b/rocketmq-research/src/test/java/com/alibaba/research/fastjson/TestEqual.java new file mode 100644 index 00000000..1cbbaa39 --- /dev/null +++ b/rocketmq-research/src/test/java/com/alibaba/research/fastjson/TestEqual.java @@ -0,0 +1,291 @@ +package com.alibaba.research.fastjson; + +import static org.junit.Assert.assertTrue; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +import org.junit.Test; + +import com.alibaba.rocketmq.common.protocol.route.BrokerData; +import com.alibaba.rocketmq.common.protocol.route.QueueData; +import com.alibaba.rocketmq.common.protocol.route.TopicRouteData; + + +/** + * 测试equal方法 + * + * @author shijia.wxr + * @since 13-7-29 + */ +public class TestEqual { + + @Test + public void test_equal() { + TopicRouteData data1 = this.buildTopicRouteData(); + TopicRouteData data2 = this.buildTopicRouteData2(); + + assertTrue(data1.equals(data2)); + } + + + private TopicRouteData buildTopicRouteData() { + TopicRouteData topicRouteData = new TopicRouteData(); + List queueDataLit = new ArrayList(); + List brokerDataList = new ArrayList(); + + topicRouteData.setBrokerDatas(brokerDataList); + topicRouteData.setQueueDatas(queueDataLit); + + QueueData qd = new QueueData(); + qd.setBrokerName("zpullmsg-60-10"); + qd.setReadQueueNums(4); + qd.setWriteQueueNums(4); + qd.setPerm(6); + queueDataLit.add(qd); + + qd = new QueueData(); + qd.setBrokerName("zpullmsg-60-11"); + qd.setReadQueueNums(4); + qd.setWriteQueueNums(4); + qd.setPerm(6); + queueDataLit.add(qd); + + qd = new QueueData(); + qd.setBrokerName("zpullmsg-60-12"); + qd.setReadQueueNums(4); + qd.setWriteQueueNums(4); + qd.setPerm(6); + queueDataLit.add(qd); + + qd = new QueueData(); + qd.setBrokerName("zpullmsg-60-13"); + qd.setReadQueueNums(4); + qd.setWriteQueueNums(4); + qd.setPerm(6); + queueDataLit.add(qd); + + // //////////////////////////////////////// + { + BrokerData bd = new BrokerData(); + bd.setBrokerName("zpullmsg-60-10"); + HashMap brokerAddrs = new HashMap(); + brokerAddrs.put(0L, "10.228.188.18:10911"); + bd.setBrokerAddrs(brokerAddrs); + brokerDataList.add(bd); + } + + { + BrokerData bd = new BrokerData(); + bd.setBrokerName("zpullmsg-60-11"); + HashMap brokerAddrs = new HashMap(); + brokerAddrs.put(0L, "10.228.188.11:10911"); + bd.setBrokerAddrs(brokerAddrs); + brokerDataList.add(bd); + } + + { + BrokerData bd = new BrokerData(); + bd.setBrokerName("zpullmsg-60-12"); + HashMap brokerAddrs = new HashMap(); + brokerAddrs.put(0L, "10.228.188.12:10911"); + bd.setBrokerAddrs(brokerAddrs); + brokerDataList.add(bd); + } + + { + BrokerData bd = new BrokerData(); + bd.setBrokerName("zpullmsg-60-13"); + HashMap brokerAddrs = new HashMap(); + brokerAddrs.put(0L, "10.228.188.14:10911"); + bd.setBrokerAddrs(brokerAddrs); + brokerDataList.add(bd); + } + + { + BrokerData bd = new BrokerData(); + bd.setBrokerName("zpullmsg-60-14"); + HashMap brokerAddrs = new HashMap(); + brokerAddrs.put(0L, "10.228.188.14:10911"); + bd.setBrokerAddrs(brokerAddrs); + brokerDataList.add(bd); + } + + { + BrokerData bd = new BrokerData(); + bd.setBrokerName("zpullmsg-60-15"); + HashMap brokerAddrs = new HashMap(); + brokerAddrs.put(0L, "10.228.188.15:10911"); + bd.setBrokerAddrs(brokerAddrs); + brokerDataList.add(bd); + } + + { + BrokerData bd = new BrokerData(); + bd.setBrokerName("zpullmsg-60-16"); + HashMap brokerAddrs = new HashMap(); + brokerAddrs.put(0L, "10.228.188.16:10911"); + bd.setBrokerAddrs(brokerAddrs); + brokerDataList.add(bd); + } + + { + BrokerData bd = new BrokerData(); + bd.setBrokerName("zpullmsg-60-17"); + HashMap brokerAddrs = new HashMap(); + brokerAddrs.put(0L, "10.228.188.17:10911"); + bd.setBrokerAddrs(brokerAddrs); + brokerDataList.add(bd); + } + + { + BrokerData bd = new BrokerData(); + bd.setBrokerName("zpullmsg-60-18"); + HashMap brokerAddrs = new HashMap(); + brokerAddrs.put(0L, "10.228.188.18:10911"); + bd.setBrokerAddrs(brokerAddrs); + brokerDataList.add(bd); + } + + { + BrokerData bd = new BrokerData(); + bd.setBrokerName("zpullmsg-60-19"); + HashMap brokerAddrs = new HashMap(); + brokerAddrs.put(0L, "10.228.188.19:10911"); + bd.setBrokerAddrs(brokerAddrs); + brokerDataList.add(bd); + } + + return topicRouteData; + } + + + private TopicRouteData buildTopicRouteData2() { + TopicRouteData topicRouteData = new TopicRouteData(); + List queueDataLit = new ArrayList(); + List brokerDataList = new ArrayList(); + + topicRouteData.setBrokerDatas(brokerDataList); + topicRouteData.setQueueDatas(queueDataLit); + + QueueData qd = new QueueData(); + qd.setBrokerName("zpullmsg-60-10"); + qd.setReadQueueNums(4); + qd.setWriteQueueNums(4); + qd.setPerm(6); + queueDataLit.add(qd); + + qd = new QueueData(); + qd.setBrokerName("zpullmsg-60-11"); + qd.setReadQueueNums(4); + qd.setWriteQueueNums(4); + qd.setPerm(6); + queueDataLit.add(qd); + + qd = new QueueData(); + qd.setBrokerName("zpullmsg-60-12"); + qd.setReadQueueNums(4); + qd.setWriteQueueNums(4); + qd.setPerm(6); + queueDataLit.add(qd); + + qd = new QueueData(); + qd.setBrokerName("zpullmsg-60-13"); + qd.setReadQueueNums(4); + qd.setWriteQueueNums(4); + qd.setPerm(6); + queueDataLit.add(qd); + + // //////////////////////////////////////// + { + BrokerData bd = new BrokerData(); + bd.setBrokerName("zpullmsg-60-10"); + HashMap brokerAddrs = new HashMap(); + brokerAddrs.put(0L, "10.228.188.18:10911"); + bd.setBrokerAddrs(brokerAddrs); + brokerDataList.add(bd); + } + + { + BrokerData bd = new BrokerData(); + bd.setBrokerName("zpullmsg-60-11"); + HashMap brokerAddrs = new HashMap(); + brokerAddrs.put(0L, "10.228.188.11:10911"); + bd.setBrokerAddrs(brokerAddrs); + brokerDataList.add(bd); + } + + { + BrokerData bd = new BrokerData(); + bd.setBrokerName("zpullmsg-60-12"); + HashMap brokerAddrs = new HashMap(); + brokerAddrs.put(0L, "10.228.188.12:10911"); + bd.setBrokerAddrs(brokerAddrs); + brokerDataList.add(bd); + } + + { + BrokerData bd = new BrokerData(); + bd.setBrokerName("zpullmsg-60-13"); + HashMap brokerAddrs = new HashMap(); + brokerAddrs.put(0L, "10.228.188.14:10911"); + bd.setBrokerAddrs(brokerAddrs); + brokerDataList.add(bd); + } + + { + BrokerData bd = new BrokerData(); + bd.setBrokerName("zpullmsg-60-14"); + HashMap brokerAddrs = new HashMap(); + brokerAddrs.put(0L, "10.228.188.14:10911"); + bd.setBrokerAddrs(brokerAddrs); + brokerDataList.add(bd); + } + + { + BrokerData bd = new BrokerData(); + bd.setBrokerName("zpullmsg-60-15"); + HashMap brokerAddrs = new HashMap(); + brokerAddrs.put(0L, "10.228.188.15:10911"); + bd.setBrokerAddrs(brokerAddrs); + brokerDataList.add(bd); + } + + { + BrokerData bd = new BrokerData(); + bd.setBrokerName("zpullmsg-60-16"); + HashMap brokerAddrs = new HashMap(); + brokerAddrs.put(0L, "10.228.188.16:10911"); + bd.setBrokerAddrs(brokerAddrs); + brokerDataList.add(bd); + } + + { + BrokerData bd = new BrokerData(); + bd.setBrokerName("zpullmsg-60-17"); + HashMap brokerAddrs = new HashMap(); + brokerAddrs.put(0L, "10.228.188.17:10911"); + bd.setBrokerAddrs(brokerAddrs); + brokerDataList.add(bd); + } + + { + BrokerData bd = new BrokerData(); + bd.setBrokerName("zpullmsg-60-19"); + HashMap brokerAddrs = new HashMap(); + brokerAddrs.put(0L, "10.228.188.19:10911"); + bd.setBrokerAddrs(brokerAddrs); + brokerDataList.add(bd); + } + { + BrokerData bd = new BrokerData(); + bd.setBrokerName("zpullmsg-60-18"); + HashMap brokerAddrs = new HashMap(); + brokerAddrs.put(0L, "10.228.188.18:10911"); + bd.setBrokerAddrs(brokerAddrs); + brokerDataList.add(bd); + } + return topicRouteData; + } +} diff --git a/rocketmq-research/src/test/java/com/alibaba/research/fastjson/TestFastjson.java b/rocketmq-research/src/test/java/com/alibaba/research/fastjson/TestFastjson.java new file mode 100644 index 00000000..b62d6baf --- /dev/null +++ b/rocketmq-research/src/test/java/com/alibaba/research/fastjson/TestFastjson.java @@ -0,0 +1,81 @@ +package com.alibaba.research.fastjson; + +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicLong; + +import org.junit.Test; + +import com.alibaba.fastjson.JSON; +import com.alibaba.rocketmq.common.message.MessageQueue; + + +/** + * @author shijia.wxr + * @since 2013-7-13 + */ +public class TestFastjson { + @Test + public void test_atomic() { + OffsetSerializeWrapper writeObject = new OffsetSerializeWrapper(); + writeObject.getOffsetTable().put(new MessageQueue("TopicA", "Broker1", 1), new AtomicLong(100)); + writeObject.getOffsetTable().put(new MessageQueue("TopicB", "Broker2", 2), new AtomicLong(200)); + writeObject.getOffsetTable().put(new MessageQueue("TopicC", "Broker3", 3), new AtomicLong(300)); + System.out.println(writeObject); + String json = JSON.toJSONString(writeObject); + System.out.println(json); + + OffsetSerializeWrapper readObject = JSON.parseObject(json, OffsetSerializeWrapper.class); + + System.out.println(readObject); + } +} + + +class OffsetSerializeWrapper { + private ConcurrentHashMap offsetTable = + new ConcurrentHashMap(); + + + public ConcurrentHashMap getOffsetTable() { + return offsetTable; + } + + + public void setOffsetTable(ConcurrentHashMap offsetTable) { + this.offsetTable = offsetTable; + } + + + @Override + public String toString() { + return "OffsetSerializeWrapper [offsetTable=" + offsetTable + "]"; + } + + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((offsetTable == null) ? 0 : offsetTable.hashCode()); + return result; + } + + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + OffsetSerializeWrapper other = (OffsetSerializeWrapper) obj; + if (offsetTable == null) { + if (other.offsetTable != null) + return false; + } + else if (!offsetTable.equals(other.offsetTable)) + return false; + return true; + } +} diff --git a/rocketmq-store/log4j.properties b/rocketmq-store/log4j.properties deleted file mode 100644 index a7e8d544..00000000 --- a/rocketmq-store/log4j.properties +++ /dev/null @@ -1,7 +0,0 @@ -log4j.rootLogger=INFO, ServerDailyRollingFile -log4j.appender.ServerDailyRollingFile=org.apache.log4j.DailyRollingFileAppender -log4j.appender.ServerDailyRollingFile.DatePattern='.'yyyy-MM-dd -log4j.appender.ServerDailyRollingFile.File=metastore.log -log4j.appender.ServerDailyRollingFile.layout=org.apache.log4j.PatternLayout -log4j.appender.ServerDailyRollingFile.layout.ConversionPattern=[%p] [%c{1}] %d{MM-dd HH:mm:ss,SSS} [%t] - %m%n -log4j.appender.ServerDailyRollingFile.Append=true diff --git a/rocketmq-store/pom.xml b/rocketmq-store/pom.xml index b6baad18..47fcb1ee 100644 --- a/rocketmq-store/pom.xml +++ b/rocketmq-store/pom.xml @@ -1,14 +1,12 @@ - + com.alibaba.rocketmq rocketmq-all - 3.0.0-SNAPSHOT + 3.0.8-SNAPSHOT 4.0.0 jar - com.alibaba.rocketmq rocketmq-store rocketmq-store ${project.version} diff --git a/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/AllocateMapedFileService.java b/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/AllocateMapedFileService.java index 16a1f6f3..e5b8eba1 100644 --- a/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/AllocateMapedFileService.java +++ b/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/AllocateMapedFileService.java @@ -1,5 +1,17 @@ /** - * $Id: AllocateMapedFileService.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.store; @@ -12,85 +24,24 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.alibaba.rocketmq.common.MixAll; -import com.alibaba.rocketmq.common.UtilALl; import com.alibaba.rocketmq.common.ServiceThread; +import com.alibaba.rocketmq.common.UtilAll; +import com.alibaba.rocketmq.common.constant.LoggerName; /** - * ԤMapedFile + * 预分配MapedFile服务 * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * @author shijia.wxr + * @since 2013-7-21 */ public class AllocateMapedFileService extends ServiceThread { - class AllocateRequest implements Comparable { - // ļȫ· - private String filePath; - // ļС - private int fileSize; - // - private CountDownLatch countDownLatch = new CountDownLatch(1); - // MapedFile - private volatile MapedFile mapedFile = null; - - - public AllocateRequest(String filePath, int fileSize) { - this.filePath = filePath; - this.fileSize = fileSize; - } - - - public String getFilePath() { - return filePath; - } - - - public void setFilePath(String filePath) { - this.filePath = filePath; - } - - - public int getFileSize() { - return fileSize; - } - - - public void setFileSize(int fileSize) { - this.fileSize = fileSize; - } - - - public CountDownLatch getCountDownLatch() { - return countDownLatch; - } - - - public void setCountDownLatch(CountDownLatch countDownLatch) { - this.countDownLatch = countDownLatch; - } - - - public MapedFile getMapedFile() { - return mapedFile; - } - - - public void setMapedFile(MapedFile mapedFile) { - this.mapedFile = mapedFile; - } - - - public int compareTo(AllocateRequest other) { - return this.fileSize < other.fileSize ? 1 : this.fileSize > other.fileSize ? -1 : 0; - } - } - - private static final Logger log = LoggerFactory.getLogger(MixAll.StoreLoggerName); + private static final Logger log = LoggerFactory.getLogger(LoggerName.StoreLoggerName); private static int WaitTimeOut = 1000 * 5; - private ConcurrentHashMap requestTable = new ConcurrentHashMap(); - private PriorityBlockingQueue requestQueue = new PriorityBlockingQueue(); + private PriorityBlockingQueue requestQueue = + new PriorityBlockingQueue(); private volatile boolean hasException = false; @@ -141,6 +92,12 @@ public MapedFile putRequestAndReturnMapedFile(String nextFilePath, String nextNe } + @Override + public String getServiceName() { + return AllocateMapedFileService.class.getSimpleName(); + } + + public void shutdown() { this.stoped = true; this.thread.interrupt(); @@ -161,8 +118,18 @@ public void shutdown() { } + public void run() { + log.info(this.getServiceName() + " service started"); + + while (!this.isStoped() && this.mmapOperation()) + ; + + log.info(this.getServiceName() + " service end"); + } + + /** - * ֻбⲿ߳жϣŻ᷵false + * 只有被外部线程中断,才会返回false */ private boolean mmapOperation() { AllocateRequest req = null; @@ -177,12 +144,12 @@ private boolean mmapOperation() { if (req.getMapedFile() == null) { long beginTime = System.currentTimeMillis(); MapedFile mapedFile = new MapedFile(req.getFilePath(), req.getFileSize()); - long eclipseTime = UtilALl.computeEclipseTimeMilliseconds(beginTime); - // ¼10ms + long eclipseTime = UtilAll.computeEclipseTimeMilliseconds(beginTime); + // 记录大于10ms的 if (eclipseTime > 10) { int queueSize = this.requestQueue.size(); - log.warn("create mapedFile spent time(ms) " + eclipseTime + " queue size " + queueSize + " " - + req.getFilePath() + " " + req.getFileSize()); + log.warn("create mapedFile spent time(ms) " + eclipseTime + " queue size " + queueSize + + " " + req.getFilePath() + " " + req.getFileSize()); } req.setMapedFile(mapedFile); @@ -205,19 +172,65 @@ private boolean mmapOperation() { return true; } + class AllocateRequest implements Comparable { + // 文件全路径 + private String filePath; + // 文件大小 + private int fileSize; + // 计数器 + private CountDownLatch countDownLatch = new CountDownLatch(1); + // MapedFile + private volatile MapedFile mapedFile = null; - public void run() { - log.info(this.getServiceName() + " service started"); - while (!this.isStoped() && this.mmapOperation()) - ; + public AllocateRequest(String filePath, int fileSize) { + this.filePath = filePath; + this.fileSize = fileSize; + } - log.info(this.getServiceName() + " service end"); - } + public String getFilePath() { + return filePath; + } - @Override - public String getServiceName() { - return AllocateMapedFileService.class.getSimpleName(); + + public void setFilePath(String filePath) { + this.filePath = filePath; + } + + + public int getFileSize() { + return fileSize; + } + + + public void setFileSize(int fileSize) { + this.fileSize = fileSize; + } + + + public CountDownLatch getCountDownLatch() { + return countDownLatch; + } + + + public void setCountDownLatch(CountDownLatch countDownLatch) { + this.countDownLatch = countDownLatch; + } + + + public MapedFile getMapedFile() { + return mapedFile; + } + + + public void setMapedFile(MapedFile mapedFile) { + this.mapedFile = mapedFile; + } + + + public int compareTo(AllocateRequest other) { + return this.fileSize < other.fileSize ? 1 : this.fileSize > other.fileSize ? -1 : 0; + } } } diff --git a/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/AppendMessageCallback.java b/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/AppendMessageCallback.java index 6deeb3e1..90b6a604 100644 --- a/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/AppendMessageCallback.java +++ b/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/AppendMessageCallback.java @@ -1,5 +1,17 @@ /** - * $Id: AppendMessageCallback.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.store; @@ -7,22 +19,23 @@ /** - * дϢĻصӿ + * 写入消息的回调接口 * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * @author shijia.wxr + * @since 2013-7-21 */ public interface AppendMessageCallback { /** - * лϢдMapedByteBuffer + * 序列化消息后,写入MapedByteBuffer * * @param byteBuffer - * Ҫдtarget + * 要写入的target * @param maxBlank - * Ҫдtargetհ + * 要写入的target最大空白区 * @param msg - * Ҫдmessage - * @return дֽ + * 要写入的message + * @return 写入多少字节 */ public AppendMessageResult doAppend(final long fileFromOffset, final ByteBuffer byteBuffer, final int maxBlank, final Object msg); diff --git a/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/AppendMessageResult.java b/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/AppendMessageResult.java index 7d973c58..2623574b 100644 --- a/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/AppendMessageResult.java +++ b/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/AppendMessageResult.java @@ -1,28 +1,46 @@ /** - * $Id: AppendMessageResult.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.store; /** - * дϢؽ + * 向物理队列写入消息返回结果 * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * @author shijia.wxr + * @since 2013-7-21 */ public class AppendMessageResult { - // + // 返回码 private AppendMessageStatus status; - // ↑ʼд + // 从哪里开始写入 private long wroteOffset; - // дֽ + // 写入字节数 private int wroteBytes; - // ϢID + // 消息ID private String msgId; - // Ϣ洢ʱ + // 消息存储时间 private long storeTimestamp; - // д߼еoffsetݽ1 + // 写入逻辑队列的offset(递进1) private long logicsOffset; + public AppendMessageResult(AppendMessageStatus status) { + this(status, 0, 0, "", 0, 0); + } + + public AppendMessageResult(AppendMessageStatus status, long wroteOffset, int wroteBytes, String msgId, long storeTimestamp, long logicsOffset) { this.status = status; @@ -39,11 +57,6 @@ public boolean isOk() { } - public AppendMessageResult(AppendMessageStatus status) { - this(status, 0, 0, "", 0, 0); - } - - public AppendMessageStatus getStatus() { return status; } @@ -102,4 +115,13 @@ public long getLogicsOffset() { public void setLogicsOffset(long logicsOffset) { this.logicsOffset = logicsOffset; } + + + @Override + public String toString() { + return "AppendMessageResult [status=" + status + ", wroteOffset=" + wroteOffset + ", wroteBytes=" + + wroteBytes + ", msgId=" + msgId + ", storeTimestamp=" + storeTimestamp + ", logicsOffset=" + + logicsOffset + "]"; + } + } diff --git a/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/AppendMessageStatus.java b/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/AppendMessageStatus.java index 8e8aeb0f..2af1e8f2 100644 --- a/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/AppendMessageStatus.java +++ b/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/AppendMessageStatus.java @@ -1,20 +1,33 @@ /** - * $Id: AppendMessageStatus.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.store; /** - * дϢؽ + * 向物理队列写消息返回结果码 * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * @author shijia.wxr + * @since 2013-7-21 */ public enum AppendMessageStatus { - // ɹ׷Ϣ + // 成功追加消息 PUT_OK, - // ߵļĩβ + // 走到文件末尾 END_OF_FILE, - // ϢС + // 消息大小超限 MESSAGE_SIZE_EXCEEDED, - // δ֪ + // 未知错误 UNKNOWN_ERROR, } diff --git a/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/CommitLog.java b/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/CommitLog.java index 2a304ff7..f1aace4f 100644 --- a/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/CommitLog.java +++ b/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/CommitLog.java @@ -1,5 +1,17 @@ /** - * $Id: CommitLog.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.store; @@ -15,12 +27,12 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.alibaba.rocketmq.common.Message; -import com.alibaba.rocketmq.common.MessageExt; -import com.alibaba.rocketmq.common.MessageDecoder; -import com.alibaba.rocketmq.common.MixAll; -import com.alibaba.rocketmq.common.UtilALl; import com.alibaba.rocketmq.common.ServiceThread; +import com.alibaba.rocketmq.common.UtilAll; +import com.alibaba.rocketmq.common.constant.LoggerName; +import com.alibaba.rocketmq.common.message.MessageConst; +import com.alibaba.rocketmq.common.message.MessageDecoder; +import com.alibaba.rocketmq.common.message.MessageExt; import com.alibaba.rocketmq.common.sysflag.MessageSysFlag; import com.alibaba.rocketmq.store.config.BrokerRole; import com.alibaba.rocketmq.store.config.FlushDiskType; @@ -29,497 +41,620 @@ /** - * CommitLogʵ + * CommitLog实现 * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * @author shijia.wxr + * @since 2013-7-21 */ public class CommitLog { - private static final Logger log = LoggerFactory.getLogger(MixAll.StoreLoggerName); - // ÿConsumeQueueĵǰOffsetϢ - private HashMap topicQueueTable = new HashMap(1024); - // 洢ϢĶ + private static final Logger log = LoggerFactory.getLogger(LoggerName.StoreLoggerName); + // 每个消息对应的MAGIC CODE daa320a7 + private final static int MessageMagicCode = 0xAABBCCDD ^ 1880681586 + 8; + // 文件末尾空洞对应的MAGIC CODE cbd43194 + private final static int BlankMagicCode = 0xBBCCDDEE ^ 1880681586 + 8; + // 存储消息的队列 private final MapedFileQueue mapedFileQueue; - // 洢 + // 存储顶层对象 private final DefaultMessageStore defaultMessageStore; - // CommitLogˢ̷ + // CommitLog刷盘服务 private final FlushCommitLogService flushCommitLogService; - // ÿϢӦMAGIC CODE daa320a7 - private final static int MessageMagicCode = 0xAABBCCDD ^ 1880681586 + 8; - // ļĩβնӦMAGIC CODE cbd43194 - private final static int BlankMagicCode = 0xBBCCDDEE ^ 1880681586 + 8; - // 洢ϢʱĻصӿ + // 存储消息时的回调接口 private final AppendMessageCallback appendMessageCallback; + // 用来保存每个ConsumeQueue的当前最大Offset信息 + private HashMap topicQueueTable = new HashMap( + 1024); - abstract class FlushCommitLogService extends ServiceThread { - } /** - * 첽ʵʱˢ̷ + * 构造函数 */ - class FlushRealTimeService extends FlushCommitLogService { - private static final int RetryTimesOver = 3; - private long lastFlushTimestamp = 0; - private long printTimes = 0; - + public CommitLog(final DefaultMessageStore defaultMessageStore) { + this.mapedFileQueue = + new MapedFileQueue(defaultMessageStore.getMessageStoreConfig().getStorePathCommitLog(), + defaultMessageStore.getMessageStoreConfig().getMapedFileSizeCommitLog(), + defaultMessageStore.getAllocateMapedFileService()); + this.defaultMessageStore = defaultMessageStore; - private void printFlushProgress() { - CommitLog.log.info("how much disk fall behind memory, " - + CommitLog.this.mapedFileQueue.howMuchFallBehind()); + if (FlushDiskType.SYNC_FLUSH == defaultMessageStore.getMessageStoreConfig().getFlushDiskType()) { + this.flushCommitLogService = new GroupCommitService(); + } + else { + this.flushCommitLogService = new FlushRealTimeService(); } + this.appendMessageCallback = + new DefaultAppendMessageCallback(defaultMessageStore.getMessageStoreConfig() + .getMaxMessageSize()); + } - public void run() { - CommitLog.log.info(this.getServiceName() + " service started"); - while (!this.isStoped()) { - int interval = - CommitLog.this.defaultMessageStore.getMessageStoreConfig().getFlushIntervalCommitLog(); - int flushPhysicQueueLeastPages = - CommitLog.this.defaultMessageStore.getMessageStoreConfig().getFlushCommitLogLeastPages(); + public boolean load() { + boolean result = this.mapedFileQueue.load(); + log.info("load commit log " + (result ? "OK" : "Failed")); + return result; + } - int flushPhysicQueueThoroughInterval = - CommitLog.this.defaultMessageStore.getMessageStoreConfig() - .getFlushCommitLogThoroughInterval(); - boolean printFlushProgress = false; + public void start() { + this.flushCommitLogService.start(); + } - // ʱˢ̣ʱӡˢ̽ - long currentTimeMillis = System.currentTimeMillis(); - if (currentTimeMillis >= (this.lastFlushTimestamp + flushPhysicQueueThoroughInterval)) { - this.lastFlushTimestamp = currentTimeMillis; - flushPhysicQueueLeastPages = 0; - printFlushProgress = ((printTimes++ % 10) == 0); - } - try { - this.waitForRunning(interval); + public void shutdown() { + this.flushCommitLogService.shutdown(); + } - if (printFlushProgress) { - this.printFlushProgress(); - } - CommitLog.this.mapedFileQueue.commit(flushPhysicQueueLeastPages); - long storeTimestamp = CommitLog.this.mapedFileQueue.getStoreTimestamp(); - if (storeTimestamp > 0) { - CommitLog.this.defaultMessageStore.getStoreCheckpoint().setPhysicMsgTimestamp( - storeTimestamp); - } - } - catch (Exception e) { - CommitLog.log.warn(this.getServiceName() + " service has exception. ", e); - this.printFlushProgress(); - } + public long getMinOffset() { + MapedFile mapedFile = this.mapedFileQueue.getFirstMapedFileOnLock(); + if (mapedFile != null) { + if (mapedFile.isAvailable()) { + return mapedFile.getFileFromOffset(); } - - // shutdownʱҪ֤ȫˢ̲˳ - boolean result = false; - for (int i = 0; i < RetryTimesOver && !result; i++) { - result = CommitLog.this.mapedFileQueue.commit(0); - CommitLog.log.info(this.getServiceName() + " service shutdown, retry " + (i + 1) + " times " - + (result ? "OK" : "Not OK")); + else { + return this.rollNextFile(mapedFile.getFileFromOffset()); } - - this.printFlushProgress(); - - CommitLog.log.info(this.getServiceName() + " service end"); } - - @Override - public String getServiceName() { - return FlushCommitLogService.class.getSimpleName(); - } + return -1; + } - @Override - public long getJointime() { - // CommitLogϴԻʱҪ - return 1000 * 60 * 5; - } + public long rollNextFile(final long offset) { + int mapedFileSize = this.defaultMessageStore.getMessageStoreConfig().getMapedFileSizeCommitLog(); + return (offset + mapedFileSize - offset % mapedFileSize); } - public class GroupCommitRequest { - // ǰϢӦһOffset - private final long nextOffset; - // 첽֪ͨ - private final CountDownLatch countDownLatch = new CountDownLatch(1); - // ˢǷɹ - private volatile boolean flushOK = false; - - public GroupCommitRequest(long nextOffset) { - this.nextOffset = nextOffset; - } + public long getMaxOffset() { + return this.mapedFileQueue.getMaxOffset(); + } - public long getNextOffset() { - return nextOffset; - } + public int deleteExpiredFile(// + final long expiredTime, // + final int deleteFilesInterval, // + final long intervalForcibly,// + final boolean cleanImmediately// + ) { + return this.mapedFileQueue.deleteExpiredFileByTime(expiredTime, deleteFilesInterval, + intervalForcibly, cleanImmediately); + } - public void wakeupCustomer(final boolean flushOK) { - this.flushOK = flushOK; - this.countDownLatch.countDown(); - } + /** + * 读取CommitLog数据,数据复制时使用 + */ + public SelectMapedBufferResult getData(final long offset) { + return this.getData(offset, (0 == offset ? true : false)); + } - public boolean waitForFlush(long timeout) { - try { - boolean result = this.countDownLatch.await(timeout, TimeUnit.MILLISECONDS); - return result || this.flushOK; - } - catch (InterruptedException e) { - e.printStackTrace(); - return false; - } + public SelectMapedBufferResult getData(final long offset, final boolean returnFirstOnNotFound) { + int mapedFileSize = this.defaultMessageStore.getMessageStoreConfig().getMapedFileSizeCommitLog(); + MapedFile mapedFile = this.mapedFileQueue.findMapedFileByOffset(offset, returnFirstOnNotFound); + if (mapedFile != null) { + int pos = (int) (offset % mapedFileSize); + SelectMapedBufferResult result = mapedFile.selectMapedBuffer(pos); + return result; } + + return null; } + /** - * GroupCommit Service + * 正常退出时,数据恢复,所有内存数据都已经刷盘 */ - class GroupCommitService extends FlushCommitLogService { - private volatile List requestsWrite = new ArrayList(); - private volatile List requestsRead = new ArrayList(); - - - private void swapRequests() { - List tmp = this.requestsWrite; - this.requestsWrite = this.requestsRead; - this.requestsRead = tmp; - } - + public void recoverNormally() { + boolean checkCRCOnRecover = this.defaultMessageStore.getMessageStoreConfig().isCheckCRCOnRecover(); + final List mapedFiles = this.mapedFileQueue.getMapedFiles(); + if (!mapedFiles.isEmpty()) { + // 从倒数第三个文件开始恢复 + int index = mapedFiles.size() - 3; + if (index < 0) + index = 0; - public void putRequest(final GroupCommitRequest request) { - synchronized (this) { - this.requestsWrite.add(request); - if (!this.hasNotified) { - this.hasNotified = true; - this.notify(); + MapedFile mapedFile = mapedFiles.get(index); + ByteBuffer byteBuffer = mapedFile.sliceByteBuffer(); + long processOffset = mapedFile.getFileFromOffset(); + long mapedFileOffset = 0; + while (true) { + DispatchRequest dispatchRequest = + this.checkMessageAndReturnSize(byteBuffer, checkCRCOnRecover); + int size = dispatchRequest.getMsgSize(); + // 正常数据 + if (size > 0) { + mapedFileOffset += size; + } + // 文件中间读到错误 + else if (size == -1) { + log.info("recover physics file end, " + mapedFile.getFileName()); + break; + } + // 走到文件末尾,切换至下一个文件 + // 由于返回0代表是遇到了最后的空洞,这个可以不计入truncate offset中 + else if (size == 0) { + index++; + if (index >= mapedFiles.size()) { + // 当前条件分支不可能发生 + log.info("recover last 3 physics file over, last maped file " + + mapedFile.getFileName()); + break; + } + else { + mapedFile = mapedFiles.get(index); + byteBuffer = mapedFile.sliceByteBuffer(); + processOffset = mapedFile.getFileFromOffset(); + mapedFileOffset = 0; + log.info("recover next physics file, " + mapedFile.getFileName()); + } } } + + processOffset += mapedFileOffset; + this.mapedFileQueue.setCommittedWhere(processOffset); + this.mapedFileQueue.truncateDirtyFiles(processOffset); } + } - private void doCommit() { - if (!this.requestsRead.isEmpty()) { - for (GroupCommitRequest req : this.requestsRead) { - // Ϣпһļˢ2 - boolean flushOK = false; - for (int i = 0; (i < 2) && !flushOK; i++) { - flushOK = (CommitLog.this.mapedFileQueue.getCommittedWhere() >= req.getNextOffset()); + public DispatchRequest checkMessageAndReturnSize(java.nio.ByteBuffer byteBuffer, final boolean checkCRC) { + return this.checkMessageAndReturnSize(byteBuffer, checkCRC, true); + } - if (!flushOK) { - CommitLog.this.mapedFileQueue.commit(0); - } - } - req.wakeupCustomer(flushOK); - } + /** + * 服务端使用 检查消息并返回消息大小 + * + * @return 0 表示走到文件末尾 >0 正常消息 -1 消息校验失败 + */ + public DispatchRequest checkMessageAndReturnSize(java.nio.ByteBuffer byteBuffer, final boolean checkCRC, + final boolean readBody) { + try { + java.nio.ByteBuffer byteBufferMessage = + ((DefaultAppendMessageCallback) this.appendMessageCallback).getMsgStoreItemMemory(); + byte[] bytesContent = byteBufferMessage.array(); - long storeTimestamp = CommitLog.this.mapedFileQueue.getStoreTimestamp(); - if (storeTimestamp > 0) { - CommitLog.this.defaultMessageStore.getStoreCheckpoint().setPhysicMsgTimestamp(storeTimestamp); - } + // 1 TOTALSIZE + int totalSize = byteBuffer.getInt(); - this.requestsRead.clear(); - } - else { - // ڸϢΪͬˢ̣Իߵ - CommitLog.this.mapedFileQueue.commit(0); + // 2 MAGICCODE + int magicCode = byteBuffer.getInt(); + switch (magicCode) { + case MessageMagicCode: + break; + case BlankMagicCode: + return new DispatchRequest(0); + default: + log.warn("found a illegal magic code 0x" + Integer.toHexString(magicCode)); + return new DispatchRequest(-1); } - } + // 3 BODYCRC + int bodyCRC = byteBuffer.getInt(); - public void run() { - CommitLog.log.info(this.getServiceName() + " service started"); + // 4 QUEUEID + int queueId = byteBuffer.getInt(); - while (!this.isStoped()) { - try { - this.waitForRunning(0); - this.doCommit(); - } - catch (Exception e) { - CommitLog.log.warn(this.getServiceName() + " service has exception. ", e); - } - } + // 5 FLAG + int flag = byteBuffer.getInt(); + flag = flag + 0; - // shutdown£ȴȻˢ - try { - Thread.sleep(10); - } - catch (InterruptedException e) { - CommitLog.log.warn("GroupCommitService Exception, ", e); - } + // 6 QUEUEOFFSET + long queueOffset = byteBuffer.getLong(); - synchronized (this) { - this.swapRequests(); - } + // 7 PHYSICALOFFSET + long physicOffset = byteBuffer.getLong(); - this.doCommit(); + // 8 SYSFLAG + int sysFlag = byteBuffer.getInt(); - CommitLog.log.info(this.getServiceName() + " service end"); - } + // 9 BORNTIMESTAMP + long bornTimeStamp = byteBuffer.getLong(); + bornTimeStamp = bornTimeStamp + 0; + // 10 BORNHOST(IP+PORT) + byteBuffer.get(bytesContent, 0, 8); - @Override - protected void onWaitEnd() { - this.swapRequests(); - } + // 11 STORETIMESTAMP + long storeTimestamp = byteBuffer.getLong(); + // 12 STOREHOST(IP+PORT) + byteBuffer.get(bytesContent, 0, 8); - @Override - public String getServiceName() { - return GroupCommitService.class.getSimpleName(); - } + // 13 RECONSUMETIMES + int reconsumeTimes = byteBuffer.getInt(); + + // 14 Prepared Transaction Offset + long preparedTransactionOffset = byteBuffer.getLong(); + // 15 BODY + int bodyLen = byteBuffer.getInt(); + if (bodyLen > 0) { + if (readBody) { + byteBuffer.get(bytesContent, 0, bodyLen); - @Override - public long getJointime() { - // CommitLogϴԻʱҪ - return 1000 * 60 * 5; + // 校验CRC + if (checkCRC) { + int crc = UtilAll.crc32(bytesContent, 0, bodyLen); + if (crc != bodyCRC) { + log.warn("CRC check failed " + crc + " " + bodyCRC); + return new DispatchRequest(-1); + } + } + } + else { + byteBuffer.position(byteBuffer.position() + bodyLen); + } + } + + // 16 TOPIC + byte topicLen = byteBuffer.get(); + byteBuffer.get(bytesContent, 0, topicLen); + String topic = new String(bytesContent, 0, topicLen); + + long tagsCode = 0; + String keys = ""; + + // 17 properties + short propertiesLength = byteBuffer.getShort(); + if (propertiesLength > 0) { + byteBuffer.get(bytesContent, 0, propertiesLength); + String properties = new String(bytesContent, 0, propertiesLength); + Map propertiesMap = MessageDecoder.string2messageProperties(properties); + + keys = propertiesMap.get(MessageConst.PROPERTY_KEYS); + String tags = propertiesMap.get(MessageConst.PROPERTY_TAGS); + if (tags != null && tags.length() > 0) { + tagsCode = + MessageExtBrokerInner.tagsString2tagsCode( + MessageExt.parseTopicFilterType(sysFlag), tags); + } + } + + return new DispatchRequest(// + topic,// 1 + queueId,// 2 + physicOffset,// 3 + totalSize,// 4 + tagsCode,// 5 + storeTimestamp,// 6 + queueOffset,// 7 + keys,// 8 + sysFlag,// 9 + 0L,// 10 + preparedTransactionOffset,// 11 + null// 12 + ); } + catch (BufferUnderflowException e) { + byteBuffer.position(byteBuffer.limit()); + } + catch (Exception e) { + byteBuffer.position(byteBuffer.limit()); + } + + return new DispatchRequest(-1); } - class DefaultAppendMessageCallback implements AppendMessageCallback { - // 洢ϢID - private final ByteBuffer msgIdMemory; - // 洢Ϣ - private final ByteBuffer msgStoreItemMemory; - // Ϣ󳤶 - private final int maxMessageSize; - // ļĩβնС - private static final int END_FILE_MIN_BLANK_LENGTH = 4 + 4; + public void recoverAbnormally() { + // 根据最小时间戳来恢复 + boolean checkCRCOnRecover = this.defaultMessageStore.getMessageStoreConfig().isCheckCRCOnRecover(); + final List mapedFiles = this.mapedFileQueue.getMapedFiles(); + if (!mapedFiles.isEmpty()) { + // 寻找从哪个文件开始恢复 + int index = mapedFiles.size() - 1; + MapedFile mapedFile = null; + for (; index >= 0; index--) { + mapedFile = mapedFiles.get(index); + if (this.isMapedFileMatchedRecover(mapedFile)) { + log.info("recover from this maped file " + mapedFile.getFileName()); + break; + } + } + if (index < 0) { + index = 0; + mapedFile = mapedFiles.get(index); + } - DefaultAppendMessageCallback(final int size) { - this.msgIdMemory = ByteBuffer.allocate(MessageDecoder.MSG_ID_LENGTH); - this.msgStoreItemMemory = ByteBuffer.allocate(size + END_FILE_MIN_BLANK_LENGTH); - this.maxMessageSize = size; - } + ByteBuffer byteBuffer = mapedFile.sliceByteBuffer(); + long processOffset = mapedFile.getFileFromOffset(); + long mapedFileOffset = 0; + while (true) { + DispatchRequest dispatchRequest = + this.checkMessageAndReturnSize(byteBuffer, checkCRCOnRecover); + int size = dispatchRequest.getMsgSize(); + // 正常数据 + if (size > 0) { + mapedFileOffset += size; + this.defaultMessageStore.putDispatchRequest(dispatchRequest); + } + // 文件中间读到错误 + else if (size == -1) { + log.info("recover physics file end, " + mapedFile.getFileName()); + break; + } + // 走到文件末尾,切换至下一个文件 + // 由于返回0代表是遇到了最后的空洞,这个可以不计入truncate offset中 + else if (size == 0) { + index++; + if (index >= mapedFiles.size()) { + // 当前条件分支正常情况下不应该发生 + log.info("recover physics file over, last maped file " + mapedFile.getFileName()); + break; + } + else { + mapedFile = mapedFiles.get(index); + byteBuffer = mapedFile.sliceByteBuffer(); + processOffset = mapedFile.getFileFromOffset(); + mapedFileOffset = 0; + log.info("recover next physics file, " + mapedFile.getFileName()); + } + } + } + processOffset += mapedFileOffset; + this.mapedFileQueue.setCommittedWhere(processOffset); + this.mapedFileQueue.truncateDirtyFiles(processOffset); - public ByteBuffer getMsgStoreItemMemory() { - return msgStoreItemMemory; + // 清除ConsumeQueue的多余数据 + this.defaultMessageStore.truncateDirtyLogicFiles(processOffset); } + // 物理文件都被删除情况下 + else { + this.mapedFileQueue.setCommittedWhere(0); + this.defaultMessageStore.destroyLogics(); + } + } - private void resetMsgStoreItemMemory(final int length) { - this.msgStoreItemMemory.flip(); - this.msgStoreItemMemory.limit(length); - } + private boolean isMapedFileMatchedRecover(final MapedFile mapedFile) { + ByteBuffer byteBuffer = mapedFile.sliceByteBuffer(); + int magicCode = byteBuffer.getInt(MessageDecoder.MessageMagicCodePostion); + if (magicCode != MessageMagicCode) { + return false; + } - public AppendMessageResult doAppend(final long fileFromOffset, final ByteBuffer byteBuffer, - final int maxBlank, final Object msg) { - /** - * ϢID STORETIMESTAMP + STOREHOSTADDRESS + OFFSET
- */ - MessageExtBrokerInner msgInner = (MessageExtBrokerInner) msg; - // PHY OFFSET - long wroteOffset = fileFromOffset + byteBuffer.position(); - String msgId = - MessageDecoder.createMessageId(this.msgIdMemory, (int) (msgInner.getStoreTimestamp() / 1000), - msgInner.getStoreHostBytes(), wroteOffset); + long storeTimestamp = byteBuffer.getLong(MessageDecoder.MessageStoreTimestampPostion); + if (0 == storeTimestamp) { + return false; + } - /** - * ¼ConsumeQueueϢ - */ - String key = msgInner.getTopic() + "-" + msgInner.getQueueId(); - Long queueOffset = CommitLog.this.topicQueueTable.get(key); - if (null == queueOffset) { - queueOffset = 0L; - CommitLog.this.topicQueueTable.put(key, queueOffset); + if (this.defaultMessageStore.getMessageStoreConfig().isMessageIndexEnable()// + && this.defaultMessageStore.getMessageStoreConfig().isMessageIndexSafe()) { + if (storeTimestamp <= this.defaultMessageStore.getStoreCheckpoint().getMinTimestampIndex()) { + log.info("find check timestamp, {} {}", // + storeTimestamp,// + UtilAll.timeMillisToHumanString(storeTimestamp)); + return true; } - - /** - * ϢҪ⴦ - */ - final int tranType = MessageSysFlag.getTransactionValue(msgInner.getSysFlag()); - switch (tranType) { - case MessageSysFlag.TransactionPreparedType: - queueOffset = - CommitLog.this.defaultMessageStore.getTransactionStateService().getTranStateTableOffset() - .get(); - break; - case MessageSysFlag.TransactionRollbackType: - queueOffset = msgInner.getQueueOffset(); - break; - case MessageSysFlag.TransactionNotType: - case MessageSysFlag.TransactionCommitType: - default: - break; + } + else { + if (storeTimestamp <= this.defaultMessageStore.getStoreCheckpoint().getMinTimestamp()) { + log.info("find check timestamp, {} {}", // + storeTimestamp,// + UtilAll.timeMillisToHumanString(storeTimestamp)); + return true; } + } - /** - * лϢ - */ - int propertiesLength = - msgInner.getPropertiesString() == null ? 0 : msgInner.getPropertiesString().length(); + return false; + } - int bodyLength = msgInner.getBody() == null ? 0 : msgInner.getBody().length; - int msgLen = 4 // 1 TOTALSIZE - + 4 // 2 MAGICCODE - + 4 // 3 BODYCRC - + 4 // 4 QUEUEID - + 4 // 5 FLAG - + 8 // 6 QUEUEOFFSET - + 8 // 7 PHYSICALOFFSET - + 4 // 8 SYSFLAG - + 8 // 9 BORNTIMESTAMP - + 8 // 10 BORNHOST - + 8 // 11 STORETIMESTAMP - + 8 // 12 STOREHOSTADDRESS - + 4 // 13 RECONSUMETIMES - + 8 // 14 Prepared Transaction Offset - + 4 + bodyLength // 14 BODY - + 1 + msgInner.getTopic().length() // 15 TOPIC - + 2 + propertiesLength // 16 propertiesLength - + 0; + public PutMessageResult putMessage(final MessageExtBrokerInner msg) { + // 设置存储时间 + msg.setStoreTimestamp(System.currentTimeMillis()); + // 设置消息体BODY CRC(考虑在客户端设置最合适) + msg.setBodyCRC(UtilAll.crc32(msg.getBody())); + // 返回结果 + AppendMessageResult result = null; - // Ϣ趨ֵ - if (msgLen > this.maxMessageSize) { - CommitLog.log.warn("message size exceeded, msg total size: " + msgLen + ", msg body size: " - + bodyLength + ", maxMessageSize: " + this.maxMessageSize); - return new AppendMessageResult(AppendMessageStatus.MESSAGE_SIZE_EXCEEDED); - } + StoreStatsService storeStatsService = this.defaultMessageStore.getStoreStatsService(); - // жǷ㹻ռ - if ((msgLen + END_FILE_MIN_BLANK_LENGTH) > maxBlank) { - this.resetMsgStoreItemMemory(maxBlank); - // 1 TOTALSIZE - this.msgStoreItemMemory.putInt(maxBlank); - // 2 MAGICCODE - this.msgStoreItemMemory.putInt(CommitLog.BlankMagicCode); - // 3 ʣռκֵ - // + String topic = msg.getTopic(); + int queueId = msg.getQueueId(); + long tagsCode = msg.getTagsCode(); - // ˴ΪmaxBlank - byteBuffer.put(this.msgStoreItemMemory.array(), 0, maxBlank); - return new AppendMessageResult(AppendMessageStatus.END_OF_FILE, wroteOffset, maxBlank, msgId, - msgInner.getStoreTimestamp(), queueOffset); - } + final int tranType = MessageSysFlag.getTransactionValue(msg.getSysFlag()); + if (tranType == MessageSysFlag.TransactionNotType// + || tranType == MessageSysFlag.TransactionCommitType) { + // 延时投递 + if (msg.getDelayTimeLevel() > 0) { + if (msg.getDelayTimeLevel() > this.defaultMessageStore.getScheduleMessageService() + .getMaxDelayLevel()) { + msg.setDelayTimeLevel(this.defaultMessageStore.getScheduleMessageService() + .getMaxDelayLevel()); + } - // ʼ洢ռ - this.resetMsgStoreItemMemory(msgLen); - // 1 TOTALSIZE - this.msgStoreItemMemory.putInt(msgLen); - // 2 MAGICCODE - this.msgStoreItemMemory.putInt(CommitLog.MessageMagicCode); - // 3 BODYCRC - this.msgStoreItemMemory.putInt(msgInner.getBodyCRC()); - // 4 QUEUEID - this.msgStoreItemMemory.putInt(msgInner.getQueueId()); - // 5 FLAG - this.msgStoreItemMemory.putInt(msgInner.getFlag()); - // 6 QUEUEOFFSET - this.msgStoreItemMemory.putLong(queueOffset); - // 7 PHYSICALOFFSET - this.msgStoreItemMemory.putLong(fileFromOffset + byteBuffer.position()); - // 8 SYSFLAG - this.msgStoreItemMemory.putInt(msgInner.getSysFlag()); - // 9 BORNTIMESTAMP - this.msgStoreItemMemory.putLong(msgInner.getBornTimestamp()); - // 10 BORNHOST - this.msgStoreItemMemory.put(msgInner.getBornHostBytes()); - // 11 STORETIMESTAMP - this.msgStoreItemMemory.putLong(msgInner.getStoreTimestamp()); - // 12 STOREHOSTADDRESS - this.msgStoreItemMemory.put(msgInner.getStoreHostBytes()); - // 13 RECONSUMETIMES - this.msgStoreItemMemory.putInt(msgInner.getReconsumeTimes()); - // 14 Prepared Transaction Offset - this.msgStoreItemMemory.putLong(msgInner.getPreparedTransactionOffset()); - // 15 BODY - this.msgStoreItemMemory.putInt(bodyLength); - if (bodyLength > 0) - this.msgStoreItemMemory.put(msgInner.getBody()); - // 16 TOPIC - this.msgStoreItemMemory.put((byte) msgInner.getTopic().length()); - this.msgStoreItemMemory.put(msgInner.getTopic().getBytes()); - // 17 PROPERTIES - this.msgStoreItemMemory.putShort((short) propertiesLength); - if (propertiesLength > 0) - this.msgStoreItemMemory.put(msgInner.getPropertiesString().getBytes()); + topic = ScheduleMessageService.SCHEDULE_TOPIC; + queueId = ScheduleMessageService.delayLevel2QueueId(msg.getDelayTimeLevel()); + tagsCode = + this.defaultMessageStore.getScheduleMessageService().computeDeliverTimestamp( + msg.getDelayTimeLevel(), msg.getStoreTimestamp()); - // лдϢ - byteBuffer.put(this.msgStoreItemMemory.array(), 0, msgLen); + /** + * 备份真实的topic,queueId + */ + msg.putProperty(MessageConst.PROPERTY_REAL_TOPIC, msg.getTopic()); + msg.putProperty(MessageConst.PROPERTY_REAL_QUEUE_ID, String.valueOf(msg.getQueueId())); + msg.setPropertiesString(MessageDecoder.messageProperties2String(msg.getProperties())); - AppendMessageResult result = - new AppendMessageResult(AppendMessageStatus.PUT_OK, wroteOffset, msgLen, msgId, - msgInner.getStoreTimestamp(), queueOffset); + msg.setTopic(topic); + msg.setQueueId(queueId); + } + } - switch (tranType) { - case MessageSysFlag.TransactionPreparedType: - CommitLog.this.defaultMessageStore.getTransactionStateService().getTranStateTableOffset() - .incrementAndGet(); - break; - case MessageSysFlag.TransactionRollbackType: + // 写文件要加锁 + synchronized (this) { + long beginLockTimestamp = this.defaultMessageStore.getSystemClock().now(); + + // 这里设置存储时间戳,才能保证全局有序 + msg.setStoreTimestamp(beginLockTimestamp); + + // 尝试写入 + MapedFile mapedFile = this.mapedFileQueue.getLastMapedFile(); + if (null == mapedFile) { + log.error("create maped file1 error, topic: " + msg.getTopic() + " clientAddr: " + + msg.getBornHostString()); + return new PutMessageResult(PutMessageStatus.CREATE_MAPEDFILE_FAILED, null); + } + result = mapedFile.appendMessage(msg, this.appendMessageCallback); + switch (result.getStatus()) { + // 成功追加消息 + case PUT_OK: break; - case MessageSysFlag.TransactionNotType: - case MessageSysFlag.TransactionCommitType: - // һεConsumeQueueϢ - CommitLog.this.topicQueueTable.put(key, ++queueOffset); + // 走到文件末尾 + case END_OF_FILE: + // 创建新文件,重新写消息 + mapedFile = this.mapedFileQueue.getLastMapedFile(); + if (null == mapedFile) { + log.error("create maped file2 error, topic: " + msg.getTopic() + " clientAddr: " + + msg.getBornHostString()); + return new PutMessageResult(PutMessageStatus.CREATE_MAPEDFILE_FAILED, result); + } + result = mapedFile.appendMessage(msg, this.appendMessageCallback); break; + // 消息大小超限 + case MESSAGE_SIZE_EXCEEDED: + return new PutMessageResult(PutMessageStatus.MESSAGE_ILLEGAL, result); + // 未知错误 + case UNKNOWN_ERROR: + return new PutMessageResult(PutMessageStatus.UNKNOWN_ERROR, result); default: - break; + return new PutMessageResult(PutMessageStatus.UNKNOWN_ERROR, result); } - // ؽ - return result; - } - } - + DispatchRequest dispatchRequest = new DispatchRequest(// + topic,// 1 + queueId,// 2 + result.getWroteOffset(),// 3 + result.getWroteBytes(),// 4 + tagsCode,// 5 + msg.getStoreTimestamp(),// 6 + result.getLogicsOffset(),// 7 + msg.getKeys(),// 8 + /** + * 事务部分 + */ + msg.getSysFlag(),// 9 + msg.getQueueOffset(), // 10 + msg.getPreparedTransactionOffset(),// 11 + msg.getProperty(MessageConst.PROPERTY_PRODUCER_GROUP)// 12 + ); - /** - * 캯 - */ - public CommitLog(final DefaultMessageStore defaultMessageStore) { - this.mapedFileQueue = - new MapedFileQueue(defaultMessageStore.getMessageStoreConfig().getStorePathCommitLog(), - defaultMessageStore.getMessageStoreConfig().getMapedFileSizeCommitLog(), - defaultMessageStore.getAllocateMapedFileService()); - this.defaultMessageStore = defaultMessageStore; + this.defaultMessageStore.putDispatchRequest(dispatchRequest); - if (FlushDiskType.SYNC_FLUSH == defaultMessageStore.getMessageStoreConfig().getFlushDiskType()) { - this.flushCommitLogService = new GroupCommitService(); - } - else { - this.flushCommitLogService = new FlushRealTimeService(); + long eclipseTime = this.defaultMessageStore.getSystemClock().now() - beginLockTimestamp; + if (eclipseTime > 1000) { + log.warn("putMessage in lock eclipse time(ms) " + eclipseTime); + } } - this.appendMessageCallback = - new DefaultAppendMessageCallback(defaultMessageStore.getMessageStoreConfig().getMaxMessageSize()); - } + // 返回结果 + PutMessageResult putMessageResult = new PutMessageResult(PutMessageStatus.PUT_OK, result); + // 统计消息SIZE + storeStatsService.getSinglePutMessageTopicSizeTotal(topic).addAndGet(result.getWroteBytes()); - public boolean load() { - boolean result = this.mapedFileQueue.load(); - log.info("load physic queue " + (result ? "OK" : "Failed")); - return result; - } + GroupCommitRequest request = null; + + // 同步刷盘 + if (FlushDiskType.SYNC_FLUSH == this.defaultMessageStore.getMessageStoreConfig().getFlushDiskType()) { + GroupCommitService service = (GroupCommitService) this.flushCommitLogService; + if (msg.isWaitStoreMsgOK()) { + request = new GroupCommitRequest(result.getWroteOffset() + result.getWroteBytes()); + service.putRequest(request); + boolean flushOK = + request.waitForFlush(this.defaultMessageStore.getMessageStoreConfig() + .getSyncFlushTimeout()); + if (!flushOK) { + log.error("do groupcommit, wait for flush failed, topic: " + msg.getTopic() + " tags: " + + msg.getTags() + " client address: " + msg.getBornHostString()); + putMessageResult.setPutMessageStatus(PutMessageStatus.FLUSH_DISK_TIMEOUT); + } + } + else { + service.wakeup(); + } + } + // 异步刷盘 + else { + this.flushCommitLogService.wakeup(); + } + // 同步双写 + if (BrokerRole.SYNC_MASTER == this.defaultMessageStore.getMessageStoreConfig().getBrokerRole()) { + HAService service = this.defaultMessageStore.getHaService(); + if (msg.isWaitStoreMsgOK()) { + // 判断是否要等待 + if (service.isSlaveOK(result.getWroteOffset() + result.getWroteBytes())) { + if (null == request) { + request = new GroupCommitRequest(result.getWroteOffset() + result.getWroteBytes()); + } + service.putRequest(request); - public void start() { - this.flushCommitLogService.start(); - } + service.getWaitNotifyObject().wakeupAll(); + boolean flushOK = + // TODO 此处参数与刷盘公用是否合适 + request.waitForFlush(this.defaultMessageStore.getMessageStoreConfig() + .getSyncFlushTimeout()); + if (!flushOK) { + log.error("do sync transfer other node, wait return, but failed, topic: " + + msg.getTopic() + " tags: " + msg.getTags() + " client address: " + + msg.getBornHostString()); + putMessageResult.setPutMessageStatus(PutMessageStatus.FLUSH_SLAVE_TIMEOUT); + } + } + // Slave异常 + else { + // 告诉发送方,Slave异常 + putMessageResult.setPutMessageStatus(PutMessageStatus.SLAVE_NOT_AVAILABLE); + } + } + } - public void shutdown() { - this.flushCommitLogService.shutdown(); + // 向发送方返回结果 + return putMessageResult; } - public long getMinOffset() { - MapedFile mapedFile = this.mapedFileQueue.getFirstMapedFileOnLock(); - if (mapedFile != null) { - if (mapedFile.isAvailable()) { - return mapedFile.getFileFromOffset(); + /** + * 根据offset获取特定消息的存储时间 如果出错,则返回-1 + */ + public long pickupStoretimestamp(final long offset, final int size) { + SelectMapedBufferResult result = this.getMessage(offset, size); + if (null != result) { + try { + return result.getByteBuffer().getLong(MessageDecoder.MessageStoreTimestampPostion); } - else { - return this.rollNextFile(mapedFile.getFileFromOffset()); + finally { + result.release(); } } @@ -527,18 +662,8 @@ public long getMinOffset() { } - public long getMaxOffset() { - return this.mapedFileQueue.getMaxOffset(); - } - - - public int deleteExpiredFile(final long expiredTime, final int deleteFilesInterval, final long intervalForcibly) { - return this.mapedFileQueue.deleteExpiredFileByTime(expiredTime, deleteFilesInterval, intervalForcibly); - } - - /** - * ȡϢ + * 读取消息 */ public SelectMapedBufferResult getMessage(final long offset, final int size) { int mapedFileSize = this.defaultMessageStore.getMessageStoreConfig().getMapedFileSizeCommitLog(); @@ -553,551 +678,465 @@ public SelectMapedBufferResult getMessage(final long offset, final int size) { } - public long rollNextFile(final long offset) { - int mapedFileSize = this.defaultMessageStore.getMessageStoreConfig().getMapedFileSizeCommitLog(); - return (offset + mapedFileSize - offset % mapedFileSize); - } - - - /** - * ȡCommitLogݣݸʱʹ - */ - public SelectMapedBufferResult getData(final long offset) { - return this.getData(offset, (0 == offset ? true : false)); + public HashMap getTopicQueueTable() { + return topicQueueTable; } - public SelectMapedBufferResult getData(final long offset, final boolean returnFirstOnNotFound) { - int mapedFileSize = this.defaultMessageStore.getMessageStoreConfig().getMapedFileSizeCommitLog(); - MapedFile mapedFile = this.mapedFileQueue.findMapedFileByOffset(offset, returnFirstOnNotFound); - if (mapedFile != null) { - int pos = (int) (offset % mapedFileSize); - SelectMapedBufferResult result = mapedFile.selectMapedBuffer(pos); - return result; - } - - return null; + public void setTopicQueueTable(HashMap topicQueueTable) { + this.topicQueueTable = topicQueueTable; } - public DispatchRequest checkMessageAndReturnSize(java.nio.ByteBuffer byteBuffer, final boolean checkCRC) { - return this.checkMessageAndReturnSize(byteBuffer, checkCRC, true); + public void destroy() { + this.mapedFileQueue.destroy(); } - /** - * ʹ ϢϢС - * - * @return 0 ʾߵļĩβ >0 Ϣ -1 ϢУʧ - */ - public DispatchRequest checkMessageAndReturnSize(java.nio.ByteBuffer byteBuffer, final boolean checkCRC, - final boolean readBody) { - try { - java.nio.ByteBuffer byteBufferMessage = - ((DefaultAppendMessageCallback) this.appendMessageCallback).getMsgStoreItemMemory(); - byte[] bytesContent = byteBufferMessage.array(); - - // 1 TOTALSIZE - int totalSize = byteBuffer.getInt(); - - // 2 MAGICCODE - int magicCode = byteBuffer.getInt(); - switch (magicCode) { - case MessageMagicCode: - break; - case BlankMagicCode: - return new DispatchRequest(0); - default: - log.warn("found a illegal magic code 0x" + Integer.toHexString(magicCode)); - return new DispatchRequest(-1); - } - - // 3 BODYCRC - int bodyCRC = byteBuffer.getInt(); - - // 4 QUEUEID - int queueId = byteBuffer.getInt(); - - // 5 FLAG - int flag = byteBuffer.getInt(); - flag = flag + 0; - - // 6 QUEUEOFFSET - long queueOffset = byteBuffer.getLong(); - - // 7 PHYSICALOFFSET - long physicOffset = byteBuffer.getLong(); - - // 8 SYSFLAG - int sysFlag = byteBuffer.getInt(); - - // 9 BORNTIMESTAMP - long bornTimeStamp = byteBuffer.getLong(); - bornTimeStamp = bornTimeStamp + 0; - - // 10 BORNHOSTIP+PORT - byteBuffer.get(bytesContent, 0, 8); - - // 11 STORETIMESTAMP - long storeTimestamp = byteBuffer.getLong(); - - // 12 STOREHOSTIP+PORT - byteBuffer.get(bytesContent, 0, 8); - - // 13 RECONSUMETIMES - int reconsumeTimes = byteBuffer.getInt(); - - // 14 Prepared Transaction Offset - long preparedTransactionOffset = byteBuffer.getLong(); - - // 15 BODY - int bodyLen = byteBuffer.getInt(); - if (bodyLen > 0) { - if (readBody) { - byteBuffer.get(bytesContent, 0, bodyLen); - - // УCRC - if (checkCRC) { - int crc = UtilALl.crc32(bytesContent, 0, bodyLen); - if (crc != bodyCRC) { - log.warn("CRC check failed " + crc + " " + bodyCRC); - return new DispatchRequest(-1); - } - } - } - else { - byteBuffer.position(byteBuffer.position() + bodyLen); - } - } - - // 16 TOPIC - byte topicLen = byteBuffer.get(); - byteBuffer.get(bytesContent, 0, topicLen); - String topic = new String(bytesContent, 0, topicLen); - - long tagsCode = 0; - String keys = ""; - - // 17 properties - short propertiesLength = byteBuffer.getShort(); - if (propertiesLength > 0) { - byteBuffer.get(bytesContent, 0, propertiesLength); - String properties = new String(bytesContent, 0, propertiesLength); - Map propertiesMap = MessageDecoder.string2messageProperties(properties); - - keys = propertiesMap.get(Message.PROPERTY_KEYS); - String tags = propertiesMap.get(Message.PROPERTY_TAGS); - if (tags != null && tags.length() > 0) { - tagsCode = - MessageExtBrokerInner.tagsString2tagsCode(MessageExt.parseTopicFilterType(sysFlag), - tags); - } + public boolean appendData(long startOffset, byte[] data) { + // 写文件要加锁 + synchronized (this) { + // 尝试写入 + MapedFile mapedFile = this.mapedFileQueue.getLastMapedFile(startOffset); + if (null == mapedFile) { + log.error("appendData getLastMapedFile error " + startOffset); + return false; } - return new DispatchRequest(// - topic,// 1 - queueId,// 2 - physicOffset,// 3 - totalSize,// 4 - tagsCode,// 5 - storeTimestamp,// 6 - queueOffset,// 7 - keys,// 8 - sysFlag,// 9 - 0L,// 10 - preparedTransactionOffset,// 11 - ""// 12 - ); - } - catch (BufferUnderflowException e) { - byteBuffer.position(byteBuffer.limit()); - } - catch (Exception e) { - byteBuffer.position(byteBuffer.limit()); + return mapedFile.appendMessage(data); } - - return new DispatchRequest(-1); } - /** - * ˳ʱݻָڴݶѾˢ - */ - public void recoverNormally() { - boolean checkCRCOnRecover = this.defaultMessageStore.getMessageStoreConfig().isCheckCRCOnRecover(); - final List mapedFiles = this.mapedFileQueue.getMapedFiles(); - if (!mapedFiles.isEmpty()) { - // ӵļʼָ - int index = mapedFiles.size() - 3; - if (index < 0) - index = 0; - - MapedFile mapedFile = mapedFiles.get(index); - ByteBuffer byteBuffer = mapedFile.sliceByteBuffer(); - long processOffset = mapedFile.getFileFromOffset(); - long mapedFileOffset = 0; - while (true) { - DispatchRequest dispatchRequest = this.checkMessageAndReturnSize(byteBuffer, checkCRCOnRecover); - int size = dispatchRequest.getMsgSize(); - // - if (size > 0) { - mapedFileOffset += size; - } - // ļм - else if (size == -1) { - log.info("recover physics file end, " + mapedFile.getFileName()); - break; - } - // ߵļĩβлһļ - // ڷ0ĿնԲtruncate offset - else if (size == 0) { - index++; - if (index >= mapedFiles.size()) { - // ǰ֧ܷ - log.info("recover last 3 physics file over, last maped file " + mapedFile.getFileName()); - break; - } - else { - mapedFile = mapedFiles.get(index); - byteBuffer = mapedFile.sliceByteBuffer(); - processOffset = mapedFile.getFileFromOffset(); - mapedFileOffset = 0; - log.info("recover next physics file, " + mapedFile.getFileName()); - } - } - } + public boolean retryDeleteFirstFile(final long intervalForcibly) { + return this.mapedFileQueue.retryDeleteFirstFile(intervalForcibly); + } - processOffset += mapedFileOffset; - this.mapedFileQueue.setCommittedWhere(processOffset); - this.mapedFileQueue.truncateDirtyFiles(processOffset); - } + abstract class FlushCommitLogService extends ServiceThread { } + /** + * 异步实时刷盘服务 + */ + class FlushRealTimeService extends FlushCommitLogService { + private static final int RetryTimesOver = 3; + private long lastFlushTimestamp = 0; + private long printTimes = 0; - public void recoverAbnormally() { - // Сʱָ - boolean checkCRCOnRecover = this.defaultMessageStore.getMessageStoreConfig().isCheckCRCOnRecover(); - final List mapedFiles = this.mapedFileQueue.getMapedFiles(); - if (!mapedFiles.isEmpty()) { - // ѰҴĸļʼָ - int index = mapedFiles.size() - 1; - MapedFile mapedFile = null; - for (; index >= 0; index--) { - mapedFile = mapedFiles.get(index); - if (this.isMapedFileMatchedRecover(mapedFile)) { - log.info("recover from this maped file " + mapedFile.getFileName()); - break; - } - } - if (index < 0) { - index = 0; - mapedFile = mapedFiles.get(index); - } + public void run() { + CommitLog.log.info(this.getServiceName() + " service started"); - ByteBuffer byteBuffer = mapedFile.sliceByteBuffer(); - long processOffset = mapedFile.getFileFromOffset(); - long mapedFileOffset = 0; - while (true) { - DispatchRequest dispatchRequest = this.checkMessageAndReturnSize(byteBuffer, checkCRCOnRecover); - int size = dispatchRequest.getMsgSize(); - // - if (size > 0) { - mapedFileOffset += size; - this.defaultMessageStore.putDispatchRequest(dispatchRequest); - } - // ļм - else if (size == -1) { - log.info("recover physics file end, " + mapedFile.getFileName()); - break; + while (!this.isStoped()) { + int interval = + CommitLog.this.defaultMessageStore.getMessageStoreConfig() + .getFlushIntervalCommitLog(); + int flushPhysicQueueLeastPages = + CommitLog.this.defaultMessageStore.getMessageStoreConfig() + .getFlushCommitLogLeastPages(); + + int flushPhysicQueueThoroughInterval = + CommitLog.this.defaultMessageStore.getMessageStoreConfig() + .getFlushCommitLogThoroughInterval(); + + boolean printFlushProgress = false; + + // 定时刷盘,定时打印刷盘进度 + long currentTimeMillis = System.currentTimeMillis(); + if (currentTimeMillis >= (this.lastFlushTimestamp + flushPhysicQueueThoroughInterval)) { + this.lastFlushTimestamp = currentTimeMillis; + flushPhysicQueueLeastPages = 0; + printFlushProgress = ((printTimes++ % 10) == 0); } - // ߵļĩβлһļ - // ڷ0ĿնԲtruncate offset - else if (size == 0) { - index++; - if (index >= mapedFiles.size()) { - // ǰ֧²Ӧ÷ - log.info("recover physics file over, last maped file " + mapedFile.getFileName()); - break; + + try { + this.waitForRunning(interval); + + if (printFlushProgress) { + this.printFlushProgress(); } - else { - mapedFile = mapedFiles.get(index); - byteBuffer = mapedFile.sliceByteBuffer(); - processOffset = mapedFile.getFileFromOffset(); - mapedFileOffset = 0; - log.info("recover next physics file, " + mapedFile.getFileName()); + + CommitLog.this.mapedFileQueue.commit(flushPhysicQueueLeastPages); + long storeTimestamp = CommitLog.this.mapedFileQueue.getStoreTimestamp(); + if (storeTimestamp > 0) { + CommitLog.this.defaultMessageStore.getStoreCheckpoint().setPhysicMsgTimestamp( + storeTimestamp); } } + catch (Exception e) { + CommitLog.log.warn(this.getServiceName() + " service has exception. ", e); + this.printFlushProgress(); + } } - processOffset += mapedFileOffset; - this.mapedFileQueue.setCommittedWhere(processOffset); - this.mapedFileQueue.truncateDirtyFiles(processOffset); + // 正常shutdown时,要保证全部刷盘才退出 + boolean result = false; + for (int i = 0; i < RetryTimesOver && !result; i++) { + result = CommitLog.this.mapedFileQueue.commit(0); + CommitLog.log.info(this.getServiceName() + " service shutdown, retry " + (i + 1) + " times " + + (result ? "OK" : "Not OK")); + } - // ConsumeQueueĶ - this.defaultMessageStore.truncateDirtyLogicFiles(processOffset); + this.printFlushProgress(); + + CommitLog.log.info(this.getServiceName() + " service end"); } - // ļɾ - else { - this.mapedFileQueue.setCommittedWhere(0); - this.defaultMessageStore.destroyLogics(); + + + @Override + public String getServiceName() { + return FlushCommitLogService.class.getSimpleName(); + } + + + private void printFlushProgress() { + CommitLog.log.info("how much disk fall behind memory, " + + CommitLog.this.mapedFileQueue.howMuchFallBehind()); + } + + + @Override + public long getJointime() { + // 由于CommitLog数据量较大,所以回收时间要更长 + return 1000 * 60 * 5; } } + public class GroupCommitRequest { + // 当前消息对应的下一个Offset + private final long nextOffset; + // 异步通知对象 + private final CountDownLatch countDownLatch = new CountDownLatch(1); + // 刷盘是否成功 + private volatile boolean flushOK = false; - private boolean isMapedFileMatchedRecover(final MapedFile mapedFile) { - ByteBuffer byteBuffer = mapedFile.sliceByteBuffer(); - int magicCode = byteBuffer.getInt(MessageDecoder.MessageMagicCodePostion); - if (magicCode != MessageMagicCode) { - return false; + public GroupCommitRequest(long nextOffset) { + this.nextOffset = nextOffset; } - long storeTimestamp = byteBuffer.getLong(MessageDecoder.MessageStoreTimestampPostion); - if (0 == storeTimestamp) { - return false; + + public long getNextOffset() { + return nextOffset; } - if (this.defaultMessageStore.getMessageStoreConfig().isMessageIndexEnable()) { - if (storeTimestamp <= this.defaultMessageStore.getStoreCheckpoint().getMinTimestampIndex()) { - return true; + + public void wakeupCustomer(final boolean flushOK) { + this.flushOK = flushOK; + this.countDownLatch.countDown(); + } + + + public boolean waitForFlush(long timeout) { + try { + boolean result = this.countDownLatch.await(timeout, TimeUnit.MILLISECONDS); + return result || this.flushOK; + } + catch (InterruptedException e) { + e.printStackTrace(); + return false; } } - else { - if (storeTimestamp <= this.defaultMessageStore.getStoreCheckpoint().getMinTimestamp()) { - return true; + } + + /** + * GroupCommit Service + */ + class GroupCommitService extends FlushCommitLogService { + private volatile List requestsWrite = new ArrayList(); + private volatile List requestsRead = new ArrayList(); + + + public void putRequest(final GroupCommitRequest request) { + synchronized (this) { + this.requestsWrite.add(request); + if (!this.hasNotified) { + this.hasNotified = true; + this.notify(); + } } } - return false; - } + private void swapRequests() { + List tmp = this.requestsWrite; + this.requestsWrite = this.requestsRead; + this.requestsRead = tmp; + } - public PutMessageResult putMessage(final MessageExtBrokerInner msg) { - // ô洢ʱ - msg.setStoreTimestamp(System.currentTimeMillis()); - // ϢBODY CRCڿͻʣ - msg.setBodyCRC(UtilALl.crc32(msg.getBody())); - // ؽ - AppendMessageResult result = null; - StoreStatsService storeStatsService = this.defaultMessageStore.getStoreStatsService(); + private void doCommit() { + if (!this.requestsRead.isEmpty()) { + for (GroupCommitRequest req : this.requestsRead) { + // 消息有可能在下一个文件,所以最多刷盘2次 + boolean flushOK = false; + for (int i = 0; (i < 2) && !flushOK; i++) { + flushOK = (CommitLog.this.mapedFileQueue.getCommittedWhere() >= req.getNextOffset()); - String topic = msg.getTopic(); - int queueId = msg.getQueueId(); - long tagsCode = msg.getTagsCode(); + if (!flushOK) { + CommitLog.this.mapedFileQueue.commit(0); + } + } - final int tranType = MessageSysFlag.getTransactionValue(msg.getSysFlag()); - if (tranType == MessageSysFlag.TransactionNotType// - || tranType == MessageSysFlag.TransactionCommitType) { - // ʱͶ - if (msg.getDelayTimeLevel() > 0) { - if (msg.getDelayTimeLevel() > this.defaultMessageStore.getScheduleMessageService() - .getMaxDelayLevel()) { - msg.setDelayTimeLevel(this.defaultMessageStore.getScheduleMessageService().getMaxDelayLevel()); + req.wakeupCustomer(flushOK); } - topic = ScheduleMessageService.SCHEDULE_TOPIC; - queueId = ScheduleMessageService.delayLevel2QueueId(msg.getDelayTimeLevel()); - tagsCode = - this.defaultMessageStore.getScheduleMessageService().computeDeliverTimestamp( - msg.getDelayTimeLevel(), msg.getStoreTimestamp()); - - /** - * ʵtopicqueueId - */ - msg.putProperty(Message.PROPERTY_REAL_TOPIC, msg.getTopic()); - msg.putProperty(Message.PROPERTY_REAL_QUEUE_ID, String.valueOf(msg.getQueueId())); - msg.setPropertiesString(MessageDecoder.messageProperties2String(msg.getProperties())); + long storeTimestamp = CommitLog.this.mapedFileQueue.getStoreTimestamp(); + if (storeTimestamp > 0) { + CommitLog.this.defaultMessageStore.getStoreCheckpoint().setPhysicMsgTimestamp( + storeTimestamp); + } - msg.setTopic(topic); - msg.setQueueId(queueId); + this.requestsRead.clear(); + } + else { + // 由于个别消息设置为不同步刷盘,所以会走到此流程 + CommitLog.this.mapedFileQueue.commit(0); } } - // дļҪ - synchronized (this) { - long beginLockTimestamp = this.defaultMessageStore.getSystemClock().now(); - // ô洢ʱܱ֤ȫ - msg.setStoreTimestamp(beginLockTimestamp); + public void run() { + CommitLog.log.info(this.getServiceName() + " service started"); - // д - MapedFile mapedFile = this.mapedFileQueue.getLastMapedFile(); - if (null == mapedFile) { - log.error("create maped file1 error, topic: " + msg.getTopic() + " clientAddr: " - + msg.getBornHostString()); - return new PutMessageResult(PutMessageStatus.CREATE_MAPEDFILE_FAILED, null); - } - result = mapedFile.appendMessage(msg, this.appendMessageCallback); - switch (result.getStatus()) { - // ɹ׷Ϣ - case PUT_OK: - break; - // ߵļĩβ - case END_OF_FILE: - // ļдϢ - mapedFile = this.mapedFileQueue.getLastMapedFile(); - if (null == mapedFile) { - log.error("create maped file2 error, topic: " + msg.getTopic() + " clientAddr: " - + msg.getBornHostString()); - return new PutMessageResult(PutMessageStatus.CREATE_MAPEDFILE_FAILED, result); + while (!this.isStoped()) { + try { + this.waitForRunning(0); + this.doCommit(); } - result = mapedFile.appendMessage(msg, this.appendMessageCallback); - break; - // ϢС - case MESSAGE_SIZE_EXCEEDED: - return new PutMessageResult(PutMessageStatus.MESSAGE_ILLEGAL, result); - // δ֪ - case UNKNOWN_ERROR: - return new PutMessageResult(PutMessageStatus.UNKNOWN_ERROR, result); - default: - return new PutMessageResult(PutMessageStatus.UNKNOWN_ERROR, result); + catch (Exception e) { + CommitLog.log.warn(this.getServiceName() + " service has exception. ", e); + } + } + + // 在正常shutdown情况下,等待请求到来,然后再刷盘 + try { + Thread.sleep(10); + } + catch (InterruptedException e) { + CommitLog.log.warn("GroupCommitService Exception, ", e); } - DispatchRequest dispatchRequest = new DispatchRequest(// - topic,// 1 - queueId,// 2 - result.getWroteOffset(),// 3 - result.getWroteBytes(),// 4 - tagsCode,// 5 - msg.getStoreTimestamp(),// 6 - result.getLogicsOffset(),// 7 - msg.getKeys(),// 8 - /** - * 񲿷 - */ - msg.getSysFlag(),// 9 - msg.getQueueOffset(), // 10 - msg.getPreparedTransactionOffset(),// 11 - msg.getProperty(Message.PROPERTY_PRODUCER_GROUP)// 12 - ); + synchronized (this) { + this.swapRequests(); + } - this.defaultMessageStore.putDispatchRequest(dispatchRequest); + this.doCommit(); - long eclipseTime = this.defaultMessageStore.getSystemClock().now() - beginLockTimestamp; - if (eclipseTime > 1000) { - log.warn("putMessage in lock eclipse time(ms) " + eclipseTime); - } + CommitLog.log.info(this.getServiceName() + " service end"); } - // ؽ - PutMessageResult putMessageResult = new PutMessageResult(PutMessageStatus.PUT_OK, result); - // ͳϢSIZE - storeStatsService.getPutMessageSizeTotal().addAndGet(result.getWroteBytes()); + @Override + protected void onWaitEnd() { + this.swapRequests(); + } - GroupCommitRequest request = null; - // ͬˢ - if (FlushDiskType.SYNC_FLUSH == this.defaultMessageStore.getMessageStoreConfig().getFlushDiskType()) { - GroupCommitService service = (GroupCommitService) this.flushCommitLogService; - if (msg.isWaitStoreMsgOK()) { - request = new GroupCommitRequest(result.getWroteOffset() + result.getWroteBytes()); - service.putRequest(request); - boolean flushOK = - request.waitForFlush(this.defaultMessageStore.getMessageStoreConfig() - .getSyncFlushTimeout()); - if (!flushOK) { - log.error("do groupcommit, wait for flush failed, topic: " + msg.getTopic() + " tags: " - + msg.getTags() + " client address: " + msg.getBornHostString()); - putMessageResult.setPutMessageStatus(PutMessageStatus.FLUSH_DISK_TIMEOUT); - } - } - else { - service.wakeup(); - } + @Override + public String getServiceName() { + return GroupCommitService.class.getSimpleName(); } - // 첽ˢ - else { - this.flushCommitLogService.wakeup(); + + + @Override + public long getJointime() { + // 由于CommitLog数据量较大,所以回收时间要更长 + return 1000 * 60 * 5; } + } - // ͬ˫д - if (BrokerRole.SYNC_MASTER == this.defaultMessageStore.getMessageStoreConfig().getBrokerRole()) { - HAService service = this.defaultMessageStore.getHaService(); - if (msg.isWaitStoreMsgOK()) { - // жǷҪȴ - if (service.isSlaveOK(result.getWroteOffset() + result.getWroteBytes())) { - if (null == request) { - request = new GroupCommitRequest(result.getWroteOffset() + result.getWroteBytes()); - } - service.putRequest(request); + class DefaultAppendMessageCallback implements AppendMessageCallback { + // 文件末尾空洞最小定长 + private static final int END_FILE_MIN_BLANK_LENGTH = 4 + 4; + // 存储消息ID + private final ByteBuffer msgIdMemory; + // 存储消息内容 + private final ByteBuffer msgStoreItemMemory; + // 消息的最大长度 + private final int maxMessageSize; - service.getWaitNotifyObject().wakeupAll(); - boolean flushOK = - // TODO ˴ˢ̹Ƿ - request.waitForFlush(this.defaultMessageStore.getMessageStoreConfig() - .getSyncFlushTimeout()); - if (!flushOK) { - log.error("do sync transfer other node, wait return, but failed, topic: " + msg.getTopic() - + " tags: " + msg.getTags() + " client address: " + msg.getBornHostString()); - putMessageResult.setPutMessageStatus(PutMessageStatus.FLUSH_SLAVE_TIMEOUT); - } - } - // Slave쳣 - else { - // ߷ͷSlave쳣 - putMessageResult.setPutMessageStatus(PutMessageStatus.SLAVE_NOT_AVAILABLE); - } - } + DefaultAppendMessageCallback(final int size) { + this.msgIdMemory = ByteBuffer.allocate(MessageDecoder.MSG_ID_LENGTH); + this.msgStoreItemMemory = ByteBuffer.allocate(size + END_FILE_MIN_BLANK_LENGTH); + this.maxMessageSize = size; } - // ͷؽ - return putMessageResult; - } + + public ByteBuffer getMsgStoreItemMemory() { + return msgStoreItemMemory; + } - /** - * offsetȡضϢĴ洢ʱ 򷵻-1 - */ - public long pickupStoretimestamp(final long offset, final int size) { - SelectMapedBufferResult result = this.getMessage(offset, size); - if (null != result) { - try { - return result.getByteBuffer().getLong(MessageDecoder.MessageStoreTimestampPostion); + public AppendMessageResult doAppend(final long fileFromOffset, final ByteBuffer byteBuffer, + final int maxBlank, final Object msg) { + /** + * 生成消息ID STORETIMESTAMP + STOREHOSTADDRESS + OFFSET
+ */ + MessageExtBrokerInner msgInner = (MessageExtBrokerInner) msg; + // PHY OFFSET + long wroteOffset = fileFromOffset + byteBuffer.position(); + String msgId = + MessageDecoder.createMessageId(this.msgIdMemory, msgInner.getStoreHostBytes(), + wroteOffset); + + /** + * 记录ConsumeQueue信息 + */ + String key = msgInner.getTopic() + "-" + msgInner.getQueueId(); + Long queueOffset = CommitLog.this.topicQueueTable.get(key); + if (null == queueOffset) { + queueOffset = 0L; + CommitLog.this.topicQueueTable.put(key, queueOffset); } - finally { - result.release(); + + /** + * 事务消息需要特殊处理 + */ + final int tranType = MessageSysFlag.getTransactionValue(msgInner.getSysFlag()); + switch (tranType) { + case MessageSysFlag.TransactionPreparedType: + queueOffset = + CommitLog.this.defaultMessageStore.getTransactionStateService() + .getTranStateTableOffset().get(); + break; + case MessageSysFlag.TransactionRollbackType: + queueOffset = msgInner.getQueueOffset(); + break; + case MessageSysFlag.TransactionNotType: + case MessageSysFlag.TransactionCommitType: + default: + break; } - } - return -1; - } + /** + * 序列化消息 + */ + final byte[] propertiesData = + msgInner.getPropertiesString() == null ? null : msgInner.getPropertiesString().getBytes(); + final int propertiesLength = propertiesData == null ? 0 : propertiesData.length; + final byte[] topicData = msgInner.getTopic().getBytes(); + final int topicLength = topicData == null ? 0 : topicData.length; - public HashMap getTopicQueueTable() { - return topicQueueTable; - } + final int bodyLength = msgInner.getBody() == null ? 0 : msgInner.getBody().length; + + final int msgLen = 4 // 1 TOTALSIZE + + 4 // 2 MAGICCODE + + 4 // 3 BODYCRC + + 4 // 4 QUEUEID + + 4 // 5 FLAG + + 8 // 6 QUEUEOFFSET + + 8 // 7 PHYSICALOFFSET + + 4 // 8 SYSFLAG + + 8 // 9 BORNTIMESTAMP + + 8 // 10 BORNHOST + + 8 // 11 STORETIMESTAMP + + 8 // 12 STOREHOSTADDRESS + + 4 // 13 RECONSUMETIMES + + 8 // 14 Prepared Transaction Offset + + 4 + bodyLength // 14 BODY + + 1 + topicLength // 15 TOPIC + + 2 + propertiesLength // 16 propertiesLength + + 0; + // 消息超过设定的最大值 + if (msgLen > this.maxMessageSize) { + CommitLog.log.warn("message size exceeded, msg total size: " + msgLen + ", msg body size: " + + bodyLength + ", maxMessageSize: " + this.maxMessageSize); + return new AppendMessageResult(AppendMessageStatus.MESSAGE_SIZE_EXCEEDED); + } - public void setTopicQueueTable(HashMap topicQueueTable) { - this.topicQueueTable = topicQueueTable; - } + // 判断是否有足够空余空间 + if ((msgLen + END_FILE_MIN_BLANK_LENGTH) > maxBlank) { + this.resetMsgStoreItemMemory(maxBlank); + // 1 TOTALSIZE + this.msgStoreItemMemory.putInt(maxBlank); + // 2 MAGICCODE + this.msgStoreItemMemory.putInt(CommitLog.BlankMagicCode); + // 3 剩余空间可能是任何值 + // + // 此处长度特意设置为maxBlank + byteBuffer.put(this.msgStoreItemMemory.array(), 0, maxBlank); + return new AppendMessageResult(AppendMessageStatus.END_OF_FILE, wroteOffset, maxBlank, msgId, + msgInner.getStoreTimestamp(), queueOffset); + } - public void destroy() { - this.mapedFileQueue.destroy(); - } + // 初始化存储空间 + this.resetMsgStoreItemMemory(msgLen); + // 1 TOTALSIZE + this.msgStoreItemMemory.putInt(msgLen); + // 2 MAGICCODE + this.msgStoreItemMemory.putInt(CommitLog.MessageMagicCode); + // 3 BODYCRC + this.msgStoreItemMemory.putInt(msgInner.getBodyCRC()); + // 4 QUEUEID + this.msgStoreItemMemory.putInt(msgInner.getQueueId()); + // 5 FLAG + this.msgStoreItemMemory.putInt(msgInner.getFlag()); + // 6 QUEUEOFFSET + this.msgStoreItemMemory.putLong(queueOffset); + // 7 PHYSICALOFFSET + this.msgStoreItemMemory.putLong(fileFromOffset + byteBuffer.position()); + // 8 SYSFLAG + this.msgStoreItemMemory.putInt(msgInner.getSysFlag()); + // 9 BORNTIMESTAMP + this.msgStoreItemMemory.putLong(msgInner.getBornTimestamp()); + // 10 BORNHOST + this.msgStoreItemMemory.put(msgInner.getBornHostBytes()); + // 11 STORETIMESTAMP + this.msgStoreItemMemory.putLong(msgInner.getStoreTimestamp()); + // 12 STOREHOSTADDRESS + this.msgStoreItemMemory.put(msgInner.getStoreHostBytes()); + // 13 RECONSUMETIMES + this.msgStoreItemMemory.putInt(msgInner.getReconsumeTimes()); + // 14 Prepared Transaction Offset + this.msgStoreItemMemory.putLong(msgInner.getPreparedTransactionOffset()); + // 15 BODY + this.msgStoreItemMemory.putInt(bodyLength); + if (bodyLength > 0) + this.msgStoreItemMemory.put(msgInner.getBody()); + // 16 TOPIC + this.msgStoreItemMemory.put((byte) topicLength); + this.msgStoreItemMemory.put(topicData); + // 17 PROPERTIES + this.msgStoreItemMemory.putShort((short) propertiesLength); + if (propertiesLength > 0) + this.msgStoreItemMemory.put(propertiesData); + + // 向队列缓冲区写入消息 + byteBuffer.put(this.msgStoreItemMemory.array(), 0, msgLen); + AppendMessageResult result = + new AppendMessageResult(AppendMessageStatus.PUT_OK, wroteOffset, msgLen, msgId, + msgInner.getStoreTimestamp(), queueOffset); - public boolean appendData(long startOffset, byte[] data) { - // дļҪ - synchronized (this) { - // д - MapedFile mapedFile = this.mapedFileQueue.getLastMapedFile(startOffset); - if (null == mapedFile) { - log.error("appendData getLastMapedFile error " + startOffset); - return false; + switch (tranType) { + case MessageSysFlag.TransactionPreparedType: + CommitLog.this.defaultMessageStore.getTransactionStateService().getTranStateTableOffset() + .incrementAndGet(); + break; + case MessageSysFlag.TransactionRollbackType: + break; + case MessageSysFlag.TransactionNotType: + case MessageSysFlag.TransactionCommitType: + // 更新下一次的ConsumeQueue信息 + CommitLog.this.topicQueueTable.put(key, ++queueOffset); + break; + default: + break; } - return mapedFile.appendMessage(data); + // 返回结果 + return result; } - } - public boolean retryDeleteFirstFile(final long intervalForcibly) { - return this.mapedFileQueue.retryDeleteFirstFile(intervalForcibly); + private void resetMsgStoreItemMemory(final int length) { + this.msgStoreItemMemory.flip(); + this.msgStoreItemMemory.limit(length); + } } } diff --git a/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/ConsumeQueue.java b/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/ConsumeQueue.java index b5ca94c8..becf4fac 100644 --- a/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/ConsumeQueue.java +++ b/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/ConsumeQueue.java @@ -1,5 +1,17 @@ /** - * $Id: ConsumeQueue.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.store; @@ -10,37 +22,37 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.alibaba.rocketmq.common.MixAll; +import com.alibaba.rocketmq.common.constant.LoggerName; /** - * Ѷʵ + * 消费队列实现 * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * @author shijia.wxr + * @since 2013-7-21 */ public class ConsumeQueue { - private static final Logger log = LoggerFactory.getLogger(MixAll.StoreLoggerName); - // 洢ԪС + // 存储单元大小 public static final int CQStoreUnitSize = 20; - // 洢 + private static final Logger log = LoggerFactory.getLogger(LoggerName.StoreLoggerName); + // 存储顶层对象 private final DefaultMessageStore defaultMessageStore; - // 洢ϢĶ + // 存储消息索引的队列 private final MapedFileQueue mapedFileQueue; // Topic private final String topic; // queueId private final int queueId; - // һϢӦOffset - private long maxPhysicOffset = -1; - // ߼еСOffsetɾļʱСOffset - // ʵʹҪ StoreUnitSize - private volatile long minLogicOffset = 0; - // дʱõByteBuffer + // 写索引时用到的ByteBuffer private final ByteBuffer byteBufferIndex; - - // + // 配置 private final String storePath; private final int mapedFileSize; + // 最后一个消息对应的物理Offset + private long maxPhysicOffset = -1; + // 逻辑队列的最小Offset,删除物理文件时,计算出来的最小Offset + // 实际使用需要除以 StoreUnitSize + private volatile long minLogicOffset = 0; public ConsumeQueue(// @@ -60,8 +72,7 @@ public ConsumeQueue(// + File.separator + topic// + File.separator + queueId;// - this.mapedFileQueue = - new MapedFileQueue(queueDir, mapedFileSize, defaultMessageStore.getAllocateMapedFileService()); + this.mapedFileQueue = new MapedFileQueue(queueDir, mapedFileSize, null); this.byteBufferIndex = ByteBuffer.allocate(CQStoreUnitSize); } @@ -77,7 +88,7 @@ public boolean load() { public void recover() { final List mapedFiles = this.mapedFileQueue.getMapedFiles(); if (!mapedFiles.isEmpty()) { - // ӵļʼָ + // 从倒数第三个文件开始恢复 int index = mapedFiles.size() - 3; if (index < 0) index = 0; @@ -93,25 +104,26 @@ public void recover() { int size = byteBuffer.getInt(); long tagsCode = byteBuffer.getLong(); - // ˵ǰ洢ԪЧ - // TODO жЧǷ + // 说明当前存储单元有效 + // TODO 这样判断有效是否合理? if (offset >= 0 && size > 0) { mapedFileOffset = i + CQStoreUnitSize; this.maxPhysicOffset = offset; } else { - log.info("recover current logics file over, " + mapedFile.getFileName() + " " + offset - + " " + size + " " + tagsCode); + log.info("recover current consume queue file over, " + mapedFile.getFileName() + " " + + offset + " " + size + " " + tagsCode); break; } } - // ߵļĩβлһļ + // 走到文件末尾,切换至下一个文件 if (mapedFileOffset == mapedFileSizeLogics) { index++; if (index >= mapedFiles.size()) { - // ǰ֧ܷ - log.info("recover last logics file over, last maped file " + mapedFile.getFileName()); + // 当前条件分支不可能发生 + log.info("recover last consume queue file over, last maped file " + + mapedFile.getFileName()); break; } else { @@ -119,11 +131,11 @@ public void recover() { byteBuffer = mapedFile.sliceByteBuffer(); processOffset = mapedFile.getFileFromOffset(); mapedFileOffset = 0; - log.info("recover next logics file, " + mapedFile.getFileName()); + log.info("recover next consume queue file, " + mapedFile.getFileName()); } } else { - log.info("recover current logics queue over " + mapedFile.getFileName() + " " + log.info("recover current consume queue queue over " + mapedFile.getFileName() + " " + (processOffset + mapedFileOffset)); break; } @@ -135,36 +147,26 @@ public void recover() { } - public long getMaxOffsetInQuque() { - return this.mapedFileQueue.getMaxOffset() / CQStoreUnitSize; - } - - - public long getMinOffsetInQuque() { - return this.minLogicOffset / CQStoreUnitSize; - } - - /** - * ֲҲϢʱӽtimestamp߼еoffset + * 二分查找查找消息发送时间最接近timestamp逻辑队列的offset */ public long getOffsetInQueueByTime(final long timestamp) { MapedFile mapedFile = this.mapedFileQueue.getMapedFileByTime(timestamp); if (mapedFile != null) { long offset = 0; - // low:һϢʼλ - // minLogicOffsetֵ - // minLogicOffset-mapedFile.getFileFromOffset()λÿʼЧֵ + // low:第一个索引信息的起始位置 + // minLogicOffset有设置值则从 + // minLogicOffset-mapedFile.getFileFromOffset()位置开始才是有效值 int low = minLogicOffset > mapedFile.getFileFromOffset() ? (int) (minLogicOffset - mapedFile .getFileFromOffset()) : 0; - // high:һϢʼλ + // high:最后一个索引信息的起始位置 int high = 0; int midOffset = -1, targetOffset = -1, leftOffset = -1, rightOffset = -1; long leftIndexValue = -1L, rightIndexValue = -1L; - // ȡmapedFileеӳռ(ûӳĿռ䲢᷵,᷵ļն) + // 取出该mapedFile里面所有的映射空间(没有映射的空间并不会返回,不会返回文件空洞) SelectMapedBufferResult sbr = mapedFile.selectMapedBuffer(0); if (null != sbr) { ByteBuffer byteBuffer = sbr.getByteBuffer(); @@ -176,12 +178,11 @@ public long getOffsetInQueueByTime(final long timestamp) { long phyOffset = byteBuffer.getLong(); int size = byteBuffer.getInt(); - // Ƚʱ, ۰ + // 比较时间, 折半 long storeTime = - this.defaultMessageStore.getCommitLog().pickupStoretimestamp(phyOffset, - size); + this.defaultMessageStore.getCommitLog().pickupStoretimestamp(phyOffset, size); if (storeTime < 0) { - // ûдļҵϢʱֱӷ0 + // 没有从物理文件找到消息,此时直接返回0 return 0; } else if (storeTime == timestamp) { @@ -201,23 +202,23 @@ else if (storeTime > timestamp) { } if (targetOffset != -1) { - // ѯʱϢ¼дʱ + // 查询的时间正好是消息索引记录写入的时间 offset = targetOffset; } else { if (leftIndexValue == -1) { - // timestamp ʱСڸMapedFileеһ¼¼ʱ + // timestamp 时间小于该MapedFile中第一条记录记录的时间 offset = rightOffset; } else if (rightIndexValue == -1) { - // timestamp ʱڸMapedFileһ¼¼ʱ + // timestamp 时间大于该MapedFile中最后一条记录记录的时间 offset = leftOffset; } else { - // ȡӽtimestampoffset + // 取最接近timestamp的offset offset = - Math.abs(timestamp - leftIndexValue) > Math.abs(timestamp - rightIndexValue) ? rightOffset - : leftOffset; + Math.abs(timestamp - leftIndexValue) > Math.abs(timestamp + - rightIndexValue) ? rightOffset : leftOffset; } } @@ -229,26 +230,26 @@ else if (rightIndexValue == -1) { } } - // ӳļΪʱ0 + // 映射文件被标记为不可用时返回0 return 0; } /** - * OffsetɾЧ߼ļ + * 根据物理Offset删除无效逻辑文件 */ public void truncateDirtyLogicFiles(long phyOffet) { - // ߼ÿļС + // 逻辑队列每个文件大小 int logicFileSize = this.mapedFileSize; - // ȸı߼д洢Offset + // 先改变逻辑队列存储的物理Offset this.maxPhysicOffset = phyOffet - 1; while (true) { MapedFile mapedFile = this.mapedFileQueue.getLastMapedFile2(); if (mapedFile != null) { ByteBuffer byteBuffer = mapedFile.sliceByteBuffer(); - // ȽOffset + // 先将Offset清空 mapedFile.setWrotePostion(0); mapedFile.setCommittedPosition(0); @@ -257,7 +258,7 @@ public void truncateDirtyLogicFiles(long phyOffet) { int size = byteBuffer.getInt(); byteBuffer.getLong(); - // ߼ļʼԪ + // 逻辑文件起始单元 if (0 == i) { if (offset >= phyOffet) { this.mapedFileQueue.deleteLastMapedFile(); @@ -270,11 +271,11 @@ public void truncateDirtyLogicFiles(long phyOffet) { this.maxPhysicOffset = offset; } } - // ߼ļм䵥Ԫ + // 逻辑文件中间单元 else { - // ˵ǰ洢ԪЧ + // 说明当前存储单元有效 if (offset >= 0 && size > 0) { - // ߼д洢offsetoffset򷵻 + // 如果逻辑队列存储的最大物理offset大于物理队列最大offset,则返回 if (offset >= phyOffet) { return; } @@ -284,7 +285,7 @@ public void truncateDirtyLogicFiles(long phyOffet) { mapedFile.setCommittedPosition(pos); this.maxPhysicOffset = offset; - // һMapedFileɨ꣬򷵻 + // 如果最后一个MapedFile扫描完,则返回 if (pos == logicFileSize) { return; } @@ -303,19 +304,19 @@ public void truncateDirtyLogicFiles(long phyOffet) { /** - * һϢӦеNext Offset + * 返回最后一条消息对应物理队列的Next Offset */ public long getLastOffset() { - // Offset + // 物理队列Offset long lastOffset = -1; - // ߼ÿļС + // 逻辑队列每个文件大小 int logicFileSize = this.mapedFileSize; MapedFile mapedFile = this.mapedFileQueue.getLastMapedFile2(); if (mapedFile != null) { ByteBuffer byteBuffer = mapedFile.sliceByteBuffer(); - // ȽOffset + // 先将Offset清空 mapedFile.setWrotePostion(0); mapedFile.setCommittedPosition(0); @@ -324,7 +325,7 @@ public long getLastOffset() { int size = byteBuffer.getInt(); byteBuffer.getLong(); - // ˵ǰ洢ԪЧ + // 说明当前存储单元有效 if (offset >= 0 && size > 0) { lastOffset = offset + size; int pos = i + CQStoreUnitSize; @@ -349,15 +350,15 @@ public boolean commit(final int flushLeastPages) { public int deleteExpiredFile(long offset) { int cnt = this.mapedFileQueue.deleteExpiredFileByOffset(offset, CQStoreUnitSize); - // ǷɾļҪСֵΪпļɾˣ - // ߼ļһҲɾ + // 无论是否删除文件,都需要纠正下最小值,因为有可能物理文件删除了, + // 但是逻辑文件一个也删除不了 this.correctMinOffset(offset); return cnt; } /** - * ߼еСOffsetҪȴСphyMinOffset + * 逻辑队列的最小Offset要比传入的物理最小phyMinOffset大 */ public void correctMinOffset(long phyMinOffset) { MapedFile mapedFile = this.mapedFileQueue.getFirstMapedFileOnLock(); @@ -365,7 +366,7 @@ public void correctMinOffset(long phyMinOffset) { SelectMapedBufferResult result = mapedFile.selectMapedBuffer(0); if (result != null) { try { - // Ϣ + // 有消息存在 for (int i = 0; i < result.getSize(); i += ConsumeQueue.CQStoreUnitSize) { long offsetPy = result.getByteBuffer().getLong(); result.getByteBuffer().getInt(); @@ -390,20 +391,53 @@ public void correctMinOffset(long phyMinOffset) { } + public long getMinOffsetInQuque() { + return this.minLogicOffset / CQStoreUnitSize; + } + + + public void putMessagePostionInfoWrapper(long offset, int size, long tagsCode, long storeTimestamp, + long logicOffset) { + final int MaxRetries = 5; + boolean canWrite = this.defaultMessageStore.getRunningFlags().isWriteable(); + for (int i = 0; i < MaxRetries && canWrite; i++) { + boolean result = this.putMessagePostionInfo(offset, size, tagsCode, logicOffset); + if (result) { + this.defaultMessageStore.getStoreCheckpoint().setLogicsMsgTimestamp(storeTimestamp); + return; + } + // 只有一种情况会失败,创建新的MapedFile时报错或者超时 + else { + log.warn("put commit log postion info to " + topic + ":" + queueId + " " + offset + + " failed, retry " + i + " times"); + + try { + Thread.sleep(1000 * 5); + } + catch (InterruptedException e) { + log.warn("", e); + } + } + } + + this.defaultMessageStore.getRunningFlags().makeLogicsQueueError(); + } + + /** - * 洢һ16ֽڵϢputMessagePostionInfoֻһ̵߳ãԲҪ + * 存储一个20字节的信息,putMessagePostionInfo只有一个线程调用,所以不需要加锁 * * @param offset - * ϢӦCommitLog offset + * 消息对应的CommitLog offset * @param size - * ϢCommitLog洢ĴС + * 消息在CommitLog存储的大小 * @param tagsCode - * tags ij - * @return Ƿɹ + * tags 计算出来的长整数 + * @return 是否成功 */ private boolean putMessagePostionInfo(final long offset, final int size, final long tagsCode, final long cqOffset) { - // ݻָʱߵ + // 在数据恢复时会走到这个流程 if (offset <= this.maxPhysicOffset) { return true; } @@ -418,7 +452,7 @@ private boolean putMessagePostionInfo(final long offset, final int size, final l MapedFile mapedFile = this.mapedFileQueue.getLastMapedFile(realLogicOffset); if (mapedFile != null) { - // MapedFile߼˳ + // 纠正MapedFile逻辑队列索引顺序 if (mapedFile.isFirstCreateInQueue() && cqOffset != 0 && mapedFile.getWrotePostion() == 0) { this.minLogicOffset = realLogicOffset; this.fillPreBlank(mapedFile, realLogicOffset); @@ -433,7 +467,7 @@ private boolean putMessagePostionInfo(final long offset, final int size, final l } } - // ¼offset + // 记录物理队列最大offset this.maxPhysicOffset = offset; return mapedFile.appendMessage(this.byteBufferIndex.array()); } @@ -442,34 +476,6 @@ private boolean putMessagePostionInfo(final long offset, final int size, final l } - public void putMessagePostionInfoWrapper(long offset, int size, long tagsCode, long storeTimestamp, - long logicOffset) { - final int MaxRetries = 5; - boolean canWrite = this.defaultMessageStore.getRunningFlags().isWriteable(); - for (int i = 0; i < MaxRetries && canWrite; i++) { - boolean result = this.putMessagePostionInfo(offset, size, tagsCode, logicOffset); - if (result) { - this.defaultMessageStore.getStoreCheckpoint().setLogicsMsgTimestamp(storeTimestamp); - return; - } - // ֻһʧܣµMapedFileʱ߳ʱ - else { - log.warn("put commit log postion info to " + topic + ":" + queueId + " " + offset - + " failed, retry " + i + " times"); - - try { - Thread.sleep(1000 * 5); - } - catch (InterruptedException e) { - e.printStackTrace(); - } - } - } - - this.defaultMessageStore.getRunningFlags().makeLogicsQueueError(); - } - - private void fillPreBlank(final MapedFile mapedFile, final long untilWhere) { ByteBuffer byteBuffer = ByteBuffer.allocate(CQStoreUnitSize); byteBuffer.putLong(0L); @@ -484,10 +490,10 @@ private void fillPreBlank(final MapedFile mapedFile, final long untilWhere) { /** - * Index Buffer + * 返回Index Buffer * * @param startIndex - * ʼƫ + * 起始偏移量索引 */ public SelectMapedBufferResult getIndexBuffer(final long startIndex) { int mapedFileSize = this.mapedFileSize; @@ -547,9 +553,14 @@ public void setMinLogicOffset(long minLogicOffset) { /** - * ȡǰеϢ + * 获取当前队列中的消息总数 */ public long getMessageTotalInQueue() { return this.getMaxOffsetInQuque() - this.getMinOffsetInQuque(); } + + + public long getMaxOffsetInQuque() { + return this.mapedFileQueue.getMaxOffset() / CQStoreUnitSize; + } } diff --git a/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/DefaultMessageFilter.java b/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/DefaultMessageFilter.java index f581bec9..8e34fe78 100644 --- a/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/DefaultMessageFilter.java +++ b/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/DefaultMessageFilter.java @@ -1,5 +1,17 @@ /** - * $Id: DefaultMessageFilter.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.store; @@ -7,9 +19,10 @@ /** - * Ϣ˹ʵ + * 消息过滤规则实现 * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * @author shijia.wxr + * @since 2013-7-21 */ public class DefaultMessageFilter implements MessageFilter { @@ -18,8 +31,12 @@ public boolean isMessageMatched(SubscriptionData subscriptionData, long tagsCode if (null == subscriptionData) { return true; } - // TODO - return true; + + if (subscriptionData.getSubString().equals(SubscriptionData.SUB_ALL)) { + return true; + } + + return subscriptionData.getCodeSet().contains((int) tagsCode); } } diff --git a/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/DefaultMessageStore.java b/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/DefaultMessageStore.java index 3ae55c3e..6a1c857d 100644 --- a/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/DefaultMessageStore.java +++ b/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/DefaultMessageStore.java @@ -1,5 +1,17 @@ /** - * $Id: DefaultMessageStore.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.store; @@ -14,13 +26,14 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.alibaba.rocketmq.common.MessageDecoder; -import com.alibaba.rocketmq.common.MessageExt; -import com.alibaba.rocketmq.common.MixAll; -import com.alibaba.rocketmq.common.UtilALl; import com.alibaba.rocketmq.common.ServiceThread; import com.alibaba.rocketmq.common.SystemClock; +import com.alibaba.rocketmq.common.UtilAll; +import com.alibaba.rocketmq.common.constant.LoggerName; +import com.alibaba.rocketmq.common.message.MessageDecoder; +import com.alibaba.rocketmq.common.message.MessageExt; import com.alibaba.rocketmq.common.protocol.heartbeat.SubscriptionData; +import com.alibaba.rocketmq.common.running.RunningStats; import com.alibaba.rocketmq.common.sysflag.MessageSysFlag; import com.alibaba.rocketmq.store.config.BrokerRole; import com.alibaba.rocketmq.store.config.MessageStoreConfig; @@ -33,54 +46,55 @@ /** - * 洢Ĭʵ + * 存储层默认实现 * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * @author shijia.wxr + * @since 2013-7-21 */ public class DefaultMessageStore implements MessageStore { - private static final Logger log = LoggerFactory.getLogger(MixAll.StoreLoggerName); - // 洢Ƿ - private volatile boolean shutdown = true; - // Ϣ + private static final Logger log = LoggerFactory.getLogger(LoggerName.StoreLoggerName); + // 消息过滤 private final MessageFilter messageFilter = new DefaultMessageFilter(); - // 洢 + // 存储配置 private final MessageStoreConfig messageStoreConfig; // CommitLog private final CommitLog commitLog; - // ConsumeQueue + // ConsumeQueue集合 private final ConcurrentHashMap> consumeQueueTable; - // ߼ˢ̷ + // 逻辑队列刷盘服务 private final FlushConsumeQueueService flushConsumeQueueService; - // ļ + // 清理物理文件服务 private final CleanCommitLogService cleanCommitLogService; - // ߼ļ + // 清理逻辑文件服务 private final CleanConsumeQueueService cleanConsumeQueueService; - // ַϢ + // 分发消息索引服务 private final DispatchMessageService dispatchMessageService; - // Ϣ + // 消息索引服务 private final IndexService indexService; - // ԤMapedFile + // 预分配MapedFile对象服务 private final AllocateMapedFileService allocateMapedFileService; - // нϢ·͵߼ + // 从物理队列解析消息重新发送到逻辑队列 private final ReputMessageService reputMessageService; - // HA + // HA服务 private final HAService haService; - // ʱ + // 定时服务 private final ScheduleMessageService scheduleMessageService; - // ֲʽ + // 分布式事务服务 private final TransactionStateService transactionStateService; - // ʱͳ + // 运行时数据统计 private final StoreStatsService storeStatsService; - // й̱־λ + // 运行过程标志位 private final RunningFlags runningFlags = new RunningFlags(); - // 洢 - private StoreCheckpoint storeCheckpoint; - // Ȩ޿ƺ󣬴ӡ - private AtomicLong printTimes = new AtomicLong(0); - // Żȡʱܣ1ms + // 优化获取时间性能,精度1ms private final SystemClock systemClock = new SystemClock(1); - // زӿ + // 事务回查接口 private final TransactionCheckExecuter transactionCheckExecuter; + // 存储服务是否启动 + private volatile boolean shutdown = true; + // 存储检查点 + private StoreCheckpoint storeCheckpoint; + // 权限控制后,打印间隔次数 + private AtomicLong printTimes = new AtomicLong(0); public DefaultMessageStore(final MessageStoreConfig messageStoreConfig) throws IOException { @@ -95,7 +109,8 @@ public DefaultMessageStore(final MessageStoreConfig messageStoreConfig, this.allocateMapedFileService = new AllocateMapedFileService(); this.commitLog = new CommitLog(this); this.consumeQueueTable = - new ConcurrentHashMap>(32); + new ConcurrentHashMap>( + 32); this.flushConsumeQueueService = new FlushConsumeQueueService(); this.cleanCommitLogService = new CleanCommitLogService(); @@ -105,733 +120,777 @@ public DefaultMessageStore(final MessageStoreConfig messageStoreConfig, this.storeStatsService = new StoreStatsService(); this.indexService = new IndexService(this); this.haService = new HAService(this); - this.scheduleMessageService = new ScheduleMessageService(this); this.transactionStateService = new TransactionStateService(this); switch (this.messageStoreConfig.getBrokerRole()) { case SLAVE: this.reputMessageService = new ReputMessageService(); + this.scheduleMessageService = null; break; case ASYNC_MASTER: case SYNC_MASTER: + this.reputMessageService = null; + this.scheduleMessageService = new ScheduleMessageService(this); + break; default: this.reputMessageService = null; + this.scheduleMessageService = null; } - // load˷ǰ + // load过程依赖此服务,所以提前启动 this.allocateMapedFileService.start(); this.dispatchMessageService.start(); + // 因为下面的recover会分发请求到索引服务,如果不启动,分发过程会被流控 + this.indexService.start(); + } + + + public void truncateDirtyLogicFiles(long phyOffet) { + ConcurrentHashMap> tables = + DefaultMessageStore.this.consumeQueueTable; + + for (ConcurrentHashMap maps : tables.values()) { + for (ConsumeQueue logic : maps.values()) { + logic.truncateDirtyLogicFiles(phyOffet); + } + } } + /** - * ļ + * 加载数据 + * + * @throws IOException */ - class CleanCommitLogService extends ServiceThread { - // ̿ռ侯ˮλֹͣϢڱĿģ - private final double DiskSpaveWarningLevelRatio = 0.90; + public boolean load() { + boolean result = false; - private long lastRedeleteTimestamp = 0; + try { + boolean lastExitOK = !this.isTempFileExist(); + log.info("last shutdown " + (lastExitOK ? "normally" : "abnormally")); - // ֹһɾ - private final static int MaxManualDeleteFileTimes = 20; + // load Commit Log + result = this.commitLog.load(); - // ֹɾϢ - private volatile int manualDeleteFileSeveralTimes = 0; + // load Consume Queue + result = result && this.loadConsumeQueue(); + // load 事务模块 + result = result && this.transactionStateService.load(); - public void excuteDeleteFilesManualy() { - this.manualDeleteFileSeveralTimes = MaxManualDeleteFileTimes; - DefaultMessageStore.log.info("excuteDeleteFilesManualy was invoked"); - } + // load 定时进度 + if (null != scheduleMessageService) { + result = result && this.scheduleMessageService.load(); + } + if (result) { + this.storeCheckpoint = new StoreCheckpoint(this.messageStoreConfig.getStoreCheckpoint()); - /** - * ǷɾļʱǷ - */ - private boolean isTimeToDelete() { - String when = DefaultMessageStore.this.getMessageStoreConfig().getDeleteWhen(); - if (UtilALl.isItTimeToDo(when)) { - DefaultMessageStore.log.info("it's time to reclaim disk space, " + when); - return true; + this.indexService.load(lastExitOK); + + // 尝试恢复数据 + this.recover(lastExitOK); + + log.info("load over, and the max phy offset = " + this.getMaxPhyOffset()); } + } + catch (Exception e) { + log.error("load exception", e); + result = false; + } - return false; + if (!result) { + this.allocateMapedFileService.shutdown(); } + return result; + } - /** - * ǷɾļռǷ - */ - private boolean isSpaceToDelete() { - double ratio = DefaultMessageStore.this.getMessageStoreConfig().getDiskMaxUsedSpaceRatio() / 100.0; - // ļ̿ռ - { - String storePathPhysic = DefaultMessageStore.this.getMessageStoreConfig().getStorePathCommitLog(); - double physicRatio = UtilALl.getDiskPartitionSpaceUsedPercent(storePathPhysic); - if (physicRatio > DiskSpaveWarningLevelRatio) { - boolean diskok = DefaultMessageStore.this.runningFlags.getAndMakeDiskFull(); - if (diskok) { - DefaultMessageStore.log.error("physic disk maybe full soon " + physicRatio - + ", so mark disk full"); - System.gc(); - } - } - else { - boolean diskok = DefaultMessageStore.this.runningFlags.getAndMakeDiskOK(); - if (!diskok) { - DefaultMessageStore.log.info("physic disk space OK " + physicRatio + ", so mark disk ok"); - } - } + /** + * 启动存储服务 + * + * @throws Exception + */ + public void start() throws Exception { + this.cleanCommitLogService.start(); + this.cleanConsumeQueueService.start(); - if (physicRatio < 0 || physicRatio > ratio) { - DefaultMessageStore.log.info("physic disk maybe full soon, so reclaim space, " + physicRatio); - return true; - } - } + // 在构造函数已经start了。 + // this.indexService.start(); + // 在构造函数已经start了。 + // this.dispatchMessageService.start(); + this.flushConsumeQueueService.start(); + this.commitLog.start(); + this.storeStatsService.start(); - // ߼ļ̿ռ - { - String storePathLogics = - DefaultMessageStore.this.getMessageStoreConfig().getStorePathConsumeQueue(); - double logicsRatio = UtilALl.getDiskPartitionSpaceUsedPercent(storePathLogics); - if (logicsRatio > DiskSpaveWarningLevelRatio) { - boolean diskok = DefaultMessageStore.this.runningFlags.getAndMakeDiskFull(); - if (diskok) { - DefaultMessageStore.log.error("logics disk maybe full soon " + logicsRatio - + ", so mark disk full"); - System.gc(); - } - } - else { - boolean diskok = DefaultMessageStore.this.runningFlags.getAndMakeDiskOK(); - if (!diskok) { - DefaultMessageStore.log.info("logics disk space OK " + logicsRatio + ", so mark disk ok"); - } - } + if (this.scheduleMessageService != null) { + this.scheduleMessageService.start(); + } - if (logicsRatio < 0 || logicsRatio > ratio) { - DefaultMessageStore.log.info("logics disk maybe full soon, so reclaim space, " + logicsRatio); - return true; - } - } - return false; + if (this.reputMessageService != null) { + this.reputMessageService.setReputFromOffset(this.commitLog.getMaxOffset()); + this.reputMessageService.start(); } + this.transactionStateService.start(); + this.haService.start(); - private void deleteExpiredFiles() { - int deleteCount = 0; - long fileReservedTime = DefaultMessageStore.this.getMessageStoreConfig().getFileReservedTime(); - int deletePhysicFilesInterval = - DefaultMessageStore.this.getMessageStoreConfig().getDeleteCommitLogFilesInterval(); - int destroyMapedFileIntervalForcibly = - DefaultMessageStore.this.getMessageStoreConfig().getDestroyMapedFileIntervalForcibly(); + this.createTempFile(); + this.shutdown = false; + } - boolean timeup = this.isTimeToDelete(); - boolean spacefull = this.isSpaceToDelete(); - boolean manualDelete = this.manualDeleteFileSeveralTimes > 0; - // ɾļ - if (timeup || spacefull || manualDelete) { - log.info("begin to delete before " + fileReservedTime + " hours file. timeup: " + timeup - + " spacefull: " + spacefull + " manualDeleteFileSeveralTimes: " - + this.manualDeleteFileSeveralTimes); + /** + * 关闭存储服务 + */ + public void shutdown() { + if (!this.shutdown) { + this.shutdown = true; - if (manualDelete) - this.manualDeleteFileSeveralTimes--; + try { + // 等待其他调用停止 + Thread.sleep(1000 * 3); + } + catch (InterruptedException e) { + log.error("shutdown Exception, ", e); + } - // Сʱתɺ - fileReservedTime *= 60 * 60 * 1000; - deleteCount = - DefaultMessageStore.this.commitLog.deleteExpiredFile(fileReservedTime, - deletePhysicFilesInterval, destroyMapedFileIntervalForcibly); - if (deleteCount > 0) { - DefaultMessageStore.this.cleanConsumeQueueService.wakeup(); - } - // Σˣ޷ɾļ - else if (spacefull) { - log.warn("disk space will be full soon, but delete file failed."); - } + this.transactionStateService.shutdown(); + + if (this.scheduleMessageService != null) { + this.scheduleMessageService.shutdown(); } - } + this.haService.shutdown(); - /** - * ǰļпHangסڼһ - */ - private void redeleteHangedFile() { - int interval = DefaultMessageStore.this.getMessageStoreConfig().getRedeleteHangedFileInterval(); - long currentTimestamp = System.currentTimeMillis(); - if ((currentTimestamp - this.lastRedeleteTimestamp) > interval) { - this.lastRedeleteTimestamp = currentTimestamp; - int destroyMapedFileIntervalForcibly = - DefaultMessageStore.this.getMessageStoreConfig().getDestroyMapedFileIntervalForcibly(); - if (DefaultMessageStore.this.commitLog.retryDeleteFirstFile(destroyMapedFileIntervalForcibly)) { - DefaultMessageStore.this.cleanConsumeQueueService.wakeup(); - } + this.storeStatsService.shutdown(); + this.cleanCommitLogService.shutdown(); + this.cleanConsumeQueueService.shutdown(); + this.dispatchMessageService.shutdown(); + this.indexService.shutdown(); + this.flushConsumeQueueService.shutdown(); + this.commitLog.shutdown(); + this.allocateMapedFileService.shutdown(); + if (this.reputMessageService != null) { + this.reputMessageService.shutdown(); } + this.storeCheckpoint.flush(); + this.storeCheckpoint.shutdown(); + this.deleteFile(this.messageStoreConfig.getAbortFile()); } + } - public void run() { - DefaultMessageStore.log.info(this.getServiceName() + " service started"); - int cleanResourceInterval = - DefaultMessageStore.this.getMessageStoreConfig().getCleanResourceInterval(); - while (!this.isStoped()) { - try { - this.waitForRunning(cleanResourceInterval); + public void destroy() { + this.destroyLogics(); + this.commitLog.destroy(); + this.indexService.destroy(); + this.deleteFile(this.messageStoreConfig.getAbortFile()); + this.deleteFile(this.messageStoreConfig.getStoreCheckpoint()); + } - this.deleteExpiredFiles(); - this.redeleteHangedFile(); - } - catch (Exception e) { - DefaultMessageStore.log.warn(this.getServiceName() + " service has exception. ", e); - } + public void destroyLogics() { + for (ConcurrentHashMap maps : this.consumeQueueTable.values()) { + for (ConsumeQueue logic : maps.values()) { + logic.destroy(); } - - DefaultMessageStore.log.info(this.getServiceName() + " service end"); } + } - @Override - public String getServiceName() { - return CleanCommitLogService.class.getSimpleName(); + public PutMessageResult putMessage(MessageExtBrokerInner msg) { + if (this.shutdown) { + log.warn("message store has shutdown, so putMessage is forbidden"); + return new PutMessageResult(PutMessageStatus.SERVICE_NOT_AVAILABLE, null); } + if (BrokerRole.SLAVE == this.messageStoreConfig.getBrokerRole()) { + long value = this.printTimes.getAndIncrement(); + if ((value % 50000) == 0) { + log.warn("message store is slave mode, so putMessage is forbidden "); + } - public int getManualDeleteFileSeveralTimes() { - return manualDeleteFileSeveralTimes; + return new PutMessageResult(PutMessageStatus.SERVICE_NOT_AVAILABLE, null); } + if (!this.runningFlags.isWriteable()) { + long value = this.printTimes.getAndIncrement(); + if ((value % 50000) == 0) { + log.warn("message store is not writeable, so putMessage is forbidden " + + this.runningFlags.getFlagBits()); + } - public void setManualDeleteFileSeveralTimes(int manualDeleteFileSeveralTimes) { - this.manualDeleteFileSeveralTimes = manualDeleteFileSeveralTimes; + return new PutMessageResult(PutMessageStatus.SERVICE_NOT_AVAILABLE, null); + } + else { + this.printTimes.set(0); } - } - /** - * ߼ļ - */ - class CleanConsumeQueueService extends ServiceThread { - private long lastPhysicalMinOffset = 0; + // message topic长度校验 + if (msg.getTopic().length() > Byte.MAX_VALUE) { + log.warn("putMessage message topic length too long " + msg.getTopic().length()); + return new PutMessageResult(PutMessageStatus.MESSAGE_ILLEGAL, null); + } + // message properties长度校验 + if (msg.getPropertiesString() != null && msg.getPropertiesString().length() > Short.MAX_VALUE) { + log.warn("putMessage message properties length too long " + msg.getPropertiesString().length()); + return new PutMessageResult(PutMessageStatus.MESSAGE_ILLEGAL, null); + } - private void deleteExpiredFiles() { - int deleteLogicsFilesInterval = - DefaultMessageStore.this.getMessageStoreConfig().getDeleteConsumeQueueFilesInterval(); - - long minOffset = DefaultMessageStore.this.commitLog.getMinOffset(); - if (minOffset > this.lastPhysicalMinOffset) { - this.lastPhysicalMinOffset = minOffset; - - // ɾ߼ļ - ConcurrentHashMap> tables = - DefaultMessageStore.this.consumeQueueTable; - - for (ConcurrentHashMap maps : tables.values()) { - for (ConsumeQueue logic : maps.values()) { - int deleteCount = logic.deleteExpiredFile(minOffset); - - if (deleteCount > 0 && deleteLogicsFilesInterval > 0) { - try { - Thread.sleep(deleteLogicsFilesInterval); - } - catch (InterruptedException e) { - e.printStackTrace(); - } - } - } - } + long beginTime = this.getSystemClock().now(); + PutMessageResult result = this.commitLog.putMessage(msg); + // 性能数据统计 + long eclipseTime = this.getSystemClock().now() - beginTime; + if (eclipseTime > 1000) { + log.warn("putMessage not in lock eclipse time(ms) " + eclipseTime); + } + this.storeStatsService.setPutMessageEntireTimeMax(eclipseTime); + this.storeStatsService.getSinglePutMessageTopicTimesTotal(msg.getTopic()).incrementAndGet(); - // ɾ־RedoLog - DefaultMessageStore.this.transactionStateService.getTranRedoLog().deleteExpiredFile(minOffset); - // ɾ־StateTable - DefaultMessageStore.this.transactionStateService.deleteExpiredStateFile(minOffset); - // ɾ - DefaultMessageStore.this.indexService.deleteExpiredFile(minOffset); - } + if (null == result || !result.isOk()) { + this.storeStatsService.getPutMessageFailedTimes().incrementAndGet(); } + return result; + } - public void run() { - DefaultMessageStore.log.info(this.getServiceName() + " service started"); - int cleanResourceInterval = - DefaultMessageStore.this.getMessageStoreConfig().getCleanResourceInterval(); - while (!this.isStoped()) { - try { - this.deleteExpiredFiles(); - this.waitForRunning(cleanResourceInterval); - } - catch (Exception e) { - DefaultMessageStore.log.warn(this.getServiceName() + " service has exception. ", e); - } - } + public SystemClock getSystemClock() { + return systemClock; + } - DefaultMessageStore.log.info(this.getServiceName() + " service end"); - } + public GetMessageResult getMessage(final String topic, final int queueId, final long offset, + final int maxMsgNums, final SubscriptionData subscriptionData) { + if (this.shutdown) { + log.warn("message store has shutdown, so getMessage is forbidden"); + return null; + } - @Override - public String getServiceName() { - return CleanConsumeQueueService.class.getSimpleName(); + if (!this.runningFlags.isReadable()) { + log.warn("message store is not readable, so getMessage is forbidden " + + this.runningFlags.getFlagBits()); + return null; } - } - /** - * ߼ˢ̷ - */ - class FlushConsumeQueueService extends ServiceThread { - private static final int RetryTimesOver = 3; - private long lastFlushTimestamp = 0; + long beginTime = this.getSystemClock().now(); + // 枚举变量,取消息结果 + GetMessageStatus status = GetMessageStatus.NO_MESSAGE_IN_QUEUE; + // 当被过滤后,返回下一次开始的Offset + long nextBeginOffset = offset; + // 逻辑队列中的最小Offset + long minOffset = 0; + // 逻辑队列中的最大Offset + long maxOffset = 0; - private void doFlush(int retryTimes) { - int flushConsumeQueueLeastPages = - DefaultMessageStore.this.getMessageStoreConfig().getFlushConsumeQueueLeastPages(); + GetMessageResult getResult = new GetMessageResult(); - if (retryTimes == RetryTimesOver) { - flushConsumeQueueLeastPages = 0; + ConsumeQueue consumeQueue = findConsumeQueue(topic, queueId); + if (consumeQueue != null) { + minOffset = consumeQueue.getMinOffsetInQuque(); + maxOffset = consumeQueue.getMaxOffsetInQuque(); + + if (maxOffset == 0) { + status = GetMessageStatus.NO_MESSAGE_IN_QUEUE; + nextBeginOffset = 0; + } + else if (offset < minOffset) { + status = GetMessageStatus.OFFSET_TOO_SMALL; + nextBeginOffset = minOffset; + } + else if (offset == maxOffset) { + status = GetMessageStatus.OFFSET_OVERFLOW_ONE; + nextBeginOffset = offset; + } + else if (offset > maxOffset) { + status = GetMessageStatus.OFFSET_OVERFLOW_BADLY; + nextBeginOffset = maxOffset; } + else { + SelectMapedBufferResult bufferConsumeQueue = consumeQueue.getIndexBuffer(offset); + if (bufferConsumeQueue != null) { + try { + status = GetMessageStatus.NO_MATCHED_MESSAGE; - long logicsMsgTimestamp = 0; + long nextPhyFileStartOffset = Long.MIN_VALUE; + long maxPhyOffsetPulling = 0; - // ʱˢ - int flushConsumeQueueThoroughInterval = - DefaultMessageStore.this.getMessageStoreConfig().getFlushConsumeQueueThoroughInterval(); - long currentTimeMillis = System.currentTimeMillis(); - if (currentTimeMillis >= (this.lastFlushTimestamp + flushConsumeQueueThoroughInterval)) { - this.lastFlushTimestamp = currentTimeMillis; - flushConsumeQueueLeastPages = 0; - logicsMsgTimestamp = DefaultMessageStore.this.getStoreCheckpoint().getLogicsMsgTimestamp(); - } + int i = 0; + final int MaxFilterMessageCount = 16000; + for (; i < bufferConsumeQueue.getSize() && i < MaxFilterMessageCount; i += + ConsumeQueue.CQStoreUnitSize) { + long offsetPy = bufferConsumeQueue.getByteBuffer().getLong(); + int sizePy = bufferConsumeQueue.getByteBuffer().getInt(); + long tagsCode = bufferConsumeQueue.getByteBuffer().getLong(); - ConcurrentHashMap> tables = - DefaultMessageStore.this.consumeQueueTable; + maxPhyOffsetPulling = offsetPy; - for (ConcurrentHashMap maps : tables.values()) { - for (ConsumeQueue cq : maps.values()) { - boolean result = false; - for (int i = 0; i < retryTimes && !result; i++) { - result = cq.commit(flushConsumeQueueLeastPages); - } - } - } + // 说明物理文件正在被删除 + if (nextPhyFileStartOffset != Long.MIN_VALUE) { + if (offsetPy < nextPhyFileStartOffset) + continue; + } - // Redolog - DefaultMessageStore.this.transactionStateService.getTranRedoLog().commit(flushConsumeQueueLeastPages); + // 此批消息达到上限了 + if (this.isTheBatchFull(offsetPy, sizePy, maxMsgNums, + getResult.getBufferTotalSize(), getResult.getMessageCount())) { + break; + } - if (0 == flushConsumeQueueLeastPages) { - DefaultMessageStore.this.getStoreCheckpoint().setLogicsMsgTimestamp(logicsMsgTimestamp); - DefaultMessageStore.this.getStoreCheckpoint().flush(); - } - } + // 消息过滤 + if (this.messageFilter.isMessageMatched(subscriptionData, tagsCode)) { + SelectMapedBufferResult selectResult = + this.commitLog.getMessage(offsetPy, sizePy); + if (selectResult != null) { + this.storeStatsService.getGetMessageTransferedMsgCount() + .incrementAndGet(); + getResult.addMessage(selectResult); + status = GetMessageStatus.FOUND; + nextPhyFileStartOffset = Long.MIN_VALUE; + } + else { + if (getResult.getBufferTotalSize() == 0) { + status = GetMessageStatus.MESSAGE_WAS_REMOVING; + } + + // 物理文件正在被删除,尝试跳过 + nextPhyFileStartOffset = this.commitLog.rollNextFile(offsetPy); + } + } + else { + if (getResult.getBufferTotalSize() == 0) { + status = GetMessageStatus.NO_MATCHED_MESSAGE; + } + if (log.isDebugEnabled()) { + log.debug("message type not matched, client: " + subscriptionData + + " server: " + tagsCode); + } + } + } - public void run() { - DefaultMessageStore.log.info(this.getServiceName() + " service started"); + nextBeginOffset = offset + (i / ConsumeQueue.CQStoreUnitSize); - while (!this.isStoped()) { - try { - int interval = DefaultMessageStore.this.getMessageStoreConfig().getFlushIntervalConsumeQueue(); - this.waitForRunning(interval); - this.doFlush(1); + long diff = maxOffset - maxPhyOffsetPulling; + long memory = + (long) (StoreUtil.TotalPhysicalMemorySize * (this.messageStoreConfig + .getAccessMessageInMemoryMaxRatio() / 100.0)); + getResult.setSuggestPullingFromSlave(diff > memory); + } + finally { + // 必须释放资源 + bufferConsumeQueue.release(); + } } - catch (Exception e) { - DefaultMessageStore.log.warn(this.getServiceName() + " service has exception. ", e); + else { + status = GetMessageStatus.OFFSET_FOUND_NULL; + nextBeginOffset = consumeQueue.rollNextFile(offset); + log.warn("consumer request topic: " + topic + "offset: " + offset + " minOffset: " + + minOffset + " maxOffset: " + maxOffset + ", but access logic queue failed."); } } - - // shutdownʱҪ֤ȫˢ̲˳ - this.doFlush(RetryTimesOver); - - DefaultMessageStore.log.info(this.getServiceName() + " service end"); } - - - @Override - public String getServiceName() { - return FlushConsumeQueueService.class.getSimpleName(); + // 请求的队列Id没有 + else { + status = GetMessageStatus.NO_MATCHED_LOGIC_QUEUE; + nextBeginOffset = 0; } - - @Override - public long getJointime() { - return 1000 * 60; + if (GetMessageStatus.FOUND == status) { + this.storeStatsService.getGetMessageTimesTotalFound().incrementAndGet(); } + else { + this.storeStatsService.getGetMessageTimesTotalMiss().incrementAndGet(); + } + long eclipseTime = this.getSystemClock().now() - beginTime; + this.storeStatsService.setGetMessageEntireTimeMax(eclipseTime); + + getResult.setStatus(status); + getResult.setNextBeginOffset(nextBeginOffset); + getResult.setMaxOffset(maxOffset); + getResult.setMinOffset(minOffset); + return getResult; } + /** - * ַϢ + * 返回的是当前队列有效的最大Offset,这个Offset有对应的消息 */ - class DispatchMessageService extends ServiceThread { - private volatile List requestsWrite; - private volatile List requestsRead; - // ѻδ - private volatile int indexRequestCnt = 0; + public long getMaxOffsetInQuque(String topic, int queueId) { + ConsumeQueue logic = this.findConsumeQueue(topic, queueId); + if (logic != null) { + long offset = logic.getMaxOffsetInQuque(); + return offset; + } + return 0; + } - public DispatchMessageService(int putMsgIndexHightWater) { - putMsgIndexHightWater *= 1.5; - this.requestsWrite = new ArrayList(putMsgIndexHightWater); - this.requestsRead = new ArrayList(putMsgIndexHightWater); + + public long getMinOffsetInQuque(String topic, int queueId) { + ConsumeQueue logic = this.findConsumeQueue(topic, queueId); + if (logic != null) { + return logic.getMinOffsetInQuque(); } + return -1; + } - private void swapRequests() { - List tmp = this.requestsWrite; - this.requestsWrite = this.requestsRead; - this.requestsRead = tmp; + + public long getOffsetInQueueByTime(String topic, int queueId, long timestamp) { + ConsumeQueue logic = this.findConsumeQueue(topic, queueId); + if (logic != null) { + return logic.getOffsetInQueueByTime(timestamp); } + return 0; + } - public boolean hasRemainMessage() { - List reqs = this.requestsWrite; - if (reqs != null && !reqs.isEmpty()) { - return true; - } - reqs = this.requestsRead; - if (reqs != null && !reqs.isEmpty()) { - return true; + public MessageExt lookMessageByOffset(long commitLogOffset) { + SelectMapedBufferResult sbr = this.commitLog.getMessage(commitLogOffset, 4); + if (null != sbr) { + try { + // 1 TOTALSIZE + int size = sbr.getByteBuffer().getInt(); + return lookMessageByOffset(commitLogOffset, size); } - - return false; - } - - - public void putRequest(final DispatchRequest dispatchRequest) { - int requestsWriteSize = 0; - int putMsgIndexHightWater = - DefaultMessageStore.this.getMessageStoreConfig().getPutMsgIndexHightWater(); - synchronized (this) { - this.requestsWrite.add(dispatchRequest); - requestsWriteSize = this.requestsWrite.size(); - if (!this.hasNotified) { - this.hasNotified = true; - this.notify(); - } + finally { + sbr.release(); } + } - DefaultMessageStore.this.getStoreStatsService().setDispatchMaxBuffer(requestsWriteSize); + return null; + } - if ((requestsWriteSize > putMsgIndexHightWater) || (this.indexRequestCnt > putMsgIndexHightWater)) { - try { - if (log.isDebugEnabled()) { - log.debug("Message index buffer size " + requestsWriteSize + " " + this.indexRequestCnt - + " > high water " + putMsgIndexHightWater); - } - Thread.sleep(1); - } - catch (InterruptedException e) { - e.printStackTrace(); - } + @Override + public SelectMapedBufferResult selectOneMessageByOffset(long commitLogOffset) { + SelectMapedBufferResult sbr = this.commitLog.getMessage(commitLogOffset, 4); + if (null != sbr) { + try { + // 1 TOTALSIZE + int size = sbr.getByteBuffer().getInt(); + return this.commitLog.getMessage(commitLogOffset, size); + } + finally { + sbr.release(); } } + return null; + } - private void doDispatch() { - if (!this.requestsRead.isEmpty()) { - for (DispatchRequest req : this.requestsRead) { - - final int tranType = MessageSysFlag.getTransactionValue(req.getSysFlag()); - // 1ַϢλϢConsumeQueue - switch (tranType) { - case MessageSysFlag.TransactionNotType: - case MessageSysFlag.TransactionCommitType: - // 󷢵Consume Queue - DefaultMessageStore.this.putMessagePostionInfo(req.getTopic(), req.getQueueId(), - req.getCommitLogOffset(), req.getMsgSize(), req.getTagsCode(), - req.getStoreTimestamp(), req.getConsumeQueueOffset()); - break; - case MessageSysFlag.TransactionPreparedType: - case MessageSysFlag.TransactionRollbackType: - break; - } - - // 2Transaction State Table - switch (tranType) { - case MessageSysFlag.TransactionNotType: - break; - case MessageSysFlag.TransactionPreparedType: - // Prepared¼ - DefaultMessageStore.this.getTransactionStateService().appendPreparedTransaction( - req.getCommitLogOffset(), req.getMsgSize(), (int) (req.getStoreTimestamp() / 1000), - req.getProducerGroup().hashCode()); - break; - case MessageSysFlag.TransactionCommitType: - case MessageSysFlag.TransactionRollbackType: - DefaultMessageStore.this.getTransactionStateService().updateTransactionState(// - req.getTranStateTableOffset(),// - req.getCommitLogOffset(),// - req.getProducerGroup().hashCode(),// - tranType// - ); - break; - } - // 3¼Transaction Redo Log - switch (tranType) { - case MessageSysFlag.TransactionNotType: - break; - case MessageSysFlag.TransactionPreparedType: - // ¼redolog - DefaultMessageStore.this.getTransactionStateService().getTranRedoLog() - .putMessagePostionInfoWrapper(// - req.getCommitLogOffset(),// - req.getMsgSize(),// - TransactionStateService.PreparedMessageTagsCode,// - req.getStoreTimestamp(),// - 0L// - ); - break; - case MessageSysFlag.TransactionCommitType: - case MessageSysFlag.TransactionRollbackType: - // ¼redolog - DefaultMessageStore.this.getTransactionStateService().getTranRedoLog() - .putMessagePostionInfoWrapper(// - req.getCommitLogOffset(),// - req.getMsgSize(),// - req.getPreparedTransactionOffset(),// - req.getStoreTimestamp(),// - 0L// - ); - break; - } - } + @Override + public SelectMapedBufferResult selectOneMessageByOffset(long commitLogOffset, int msgSize) { + return this.commitLog.getMessage(commitLogOffset, msgSize); + } - if (DefaultMessageStore.this.getMessageStoreConfig().isMessageIndexEnable()) { - this.indexRequestCnt = - DefaultMessageStore.this.indexService.putRequest(this.requestsRead.toArray()); - } - this.requestsRead.clear(); - } - } + public String getRunningDataInfo() { + return this.storeStatsService.toString(); + } - public void run() { - DefaultMessageStore.log.info(this.getServiceName() + " service started"); + @Override + public HashMap getRuntimeInfo() { + HashMap result = this.storeStatsService.getRuntimeInfo(); + // 检测物理文件磁盘空间 + { + String storePathPhysic = DefaultMessageStore.this.getMessageStoreConfig().getStorePathCommitLog(); + double physicRatio = UtilAll.getDiskPartitionSpaceUsedPercent(storePathPhysic); + result.put(RunningStats.commitLogDiskRatio.name(), String.valueOf(physicRatio)); - while (!this.isStoped()) { - try { - this.waitForRunning(0); - this.doDispatch(); - } - catch (Exception e) { - DefaultMessageStore.log.warn(this.getServiceName() + " service has exception. ", e); - } - } + } - // shutdown£Ҫ֤Ϣdispatch - try { - Thread.sleep(5 * 1000); - } - catch (InterruptedException e) { - DefaultMessageStore.log.warn("DispatchMessageService Exception, ", e); - } + // 检测逻辑文件磁盘空间 + { + String storePathLogics = + DefaultMessageStore.this.getMessageStoreConfig().getStorePathConsumeQueue(); + double logicsRatio = UtilAll.getDiskPartitionSpaceUsedPercent(storePathLogics); + result.put(RunningStats.consumeQueueDiskRatio.name(), String.valueOf(logicsRatio)); + } - synchronized (this) { - this.swapRequests(); + // 延时进度 + { + if (this.scheduleMessageService != null) { + this.scheduleMessageService.buildRunningStats(result); } - - this.doDispatch(); - - DefaultMessageStore.log.info(this.getServiceName() + " service end"); } + result.put(RunningStats.commitLogMinOffset.name(), + String.valueOf(DefaultMessageStore.this.getMinPhyOffset())); + result.put(RunningStats.commitLogMaxOffset.name(), + String.valueOf(DefaultMessageStore.this.getMaxPhyOffset())); - @Override - protected void onWaitEnd() { - this.swapRequests(); - } + return result; + } - @Override - public String getServiceName() { - return DispatchMessageService.class.getSimpleName(); - } + @Override + public long getMaxPhyOffset() { + return this.commitLog.getMaxOffset(); } - /** - * SLAVE: LoadϢַ߼ - */ - class ReputMessageService extends ServiceThread { - // ↑ʼݣַ߼ - private volatile long reputFromOffset = 0; + @Override + public long getEarliestMessageTime(String topic, int queueId) { + ConsumeQueue logicQueue = this.findConsumeQueue(topic, queueId); + if (logicQueue != null) { + long minLogicOffset = logicQueue.getMinLogicOffset(); - private void doReput() { - for (boolean doNext = true; doNext;) { - SelectMapedBufferResult result = DefaultMessageStore.this.commitLog.getData(reputFromOffset); - if (result != null) { - try { - for (int readSize = 0; readSize < result.getSize() && doNext;) { - DispatchRequest dispatchRequest = - DefaultMessageStore.this.commitLog.checkMessageAndReturnSize( - result.getByteBuffer(), false, false); - int size = dispatchRequest.getMsgSize(); - // - if (size > 0) { - DefaultMessageStore.this.putDispatchRequest(dispatchRequest); - - this.reputFromOffset += size; - readSize += size; - DefaultMessageStore.this.storeStatsService.getPutMessageTimesTotal() - .incrementAndGet(); - DefaultMessageStore.this.storeStatsService.getPutMessageSizeTotal().addAndGet( - dispatchRequest.getMsgSize()); - } - // ļм - else if (size == -1) { - doNext = false; - } - // ߵļĩβлһļ - else if (size == 0) { - this.reputFromOffset = - DefaultMessageStore.this.commitLog.rollNextFile(this.reputFromOffset); - readSize = result.getSize(); - } - } - } - finally { - result.release(); - } + SelectMapedBufferResult result = + logicQueue.getIndexBuffer(minLogicOffset / ConsumeQueue.CQStoreUnitSize); + if (result != null) { + try { + final long phyOffset = result.getByteBuffer().getLong(); + final int size = result.getByteBuffer().getInt(); + long storeTime = this.getCommitLog().pickupStoretimestamp(phyOffset, size); + return storeTime; } - else { - doNext = false; + catch (Exception e) { + } + finally { + result.release(); } } } + return -1; + } - @Override - public void run() { - DefaultMessageStore.log.info(this.getServiceName() + " service started"); - while (!this.isStoped()) { + @Override + public long getMessageStoreTimeStamp(String topic, int queueId, long offset) { + ConsumeQueue logicQueue = this.findConsumeQueue(topic, queueId); + if (logicQueue != null) { + SelectMapedBufferResult result = logicQueue.getIndexBuffer(offset); + if (result != null) { try { - this.waitForRunning(1000); - this.doReput(); + final long phyOffset = result.getByteBuffer().getLong(); + final int size = result.getByteBuffer().getInt(); + long storeTime = this.getCommitLog().pickupStoretimestamp(phyOffset, size); + return storeTime; } catch (Exception e) { - DefaultMessageStore.log.warn(this.getServiceName() + " service has exception. ", e); + } + finally { + result.release(); } } - - DefaultMessageStore.log.info(this.getServiceName() + " service end"); } - - @Override - public String getServiceName() { - return ReputMessageService.class.getSimpleName(); - } + return -1; + } - public long getReputFromOffset() { - return reputFromOffset; + @Override + public long getMessageTotalInQueue(String topic, int queueId) { + ConsumeQueue logicQueue = this.findConsumeQueue(topic, queueId); + if (logicQueue != null) { + return logicQueue.getMessageTotalInQueue(); } + return -1; + } - public void setReputFromOffset(long reputFromOffset) { - this.reputFromOffset = reputFromOffset; + + @Override + public SelectMapedBufferResult getCommitLogData(final long offset) { + if (this.shutdown) { + log.warn("message store has shutdown, so getPhyQueueData is forbidden"); + return null; } + + return this.commitLog.getData(offset); } - public void truncateDirtyLogicFiles(long phyOffet) { - ConcurrentHashMap> tables = - DefaultMessageStore.this.consumeQueueTable; + @Override + public boolean appendToCommitLog(long startOffset, byte[] data) { + if (this.shutdown) { + log.warn("message store has shutdown, so appendToPhyQueue is forbidden"); + return false; + } - for (ConcurrentHashMap maps : tables.values()) { - for (ConsumeQueue logic : maps.values()) { - logic.truncateDirtyLogicFiles(phyOffet); - } + boolean result = this.commitLog.appendData(startOffset, data); + if (result) { + this.reputMessageService.wakeup(); + } + else { + log.error("appendToPhyQueue failed " + startOffset + " " + data.length); } + + return result; } - private void recover(final boolean lastExitOK) { - // Ȱָ̻Consume Queue - this.recoverConsumeQueue(); + @Override + public void excuteDeleteFilesManualy() { + this.cleanCommitLogService.excuteDeleteFilesManualy(); + } - // Ȱָ̻Tran Redo Log - this.transactionStateService.getTranRedoLog().recover(); - // ݻָ - if (lastExitOK) { - this.commitLog.recoverNormally(); - } - // 쳣ݻָOS CRASHJVM CRASH߻ - else { - this.commitLog.recoverAbnormally(); + @Override + public QueryMessageResult queryMessage(String topic, String key, int maxNum, long begin, long end) { + QueryOffsetResult queryOffsetResult = this.indexService.queryOffset(topic, key, maxNum, begin, end); + QueryMessageResult queryMessageResult = new QueryMessageResult(); - // ֤ϢܴDispatchServiceн뵽Ķ - while (this.dispatchMessageService.hasRemainMessage()) { - try { - Thread.sleep(500); - log.info("waiting dispatching message over"); - } - catch (InterruptedException e) { - e.printStackTrace(); - } + queryMessageResult.setIndexLastUpdatePhyoffset(queryOffsetResult.getIndexLastUpdatePhyoffset()); + queryMessageResult.setIndexLastUpdateTimestamp(queryOffsetResult.getIndexLastUpdateTimestamp()); + + for (Long offset : queryOffsetResult.getPhyOffsets()) { + SelectMapedBufferResult result = this.commitLog.getData(offset, false); + if (result != null) { + int size = result.getByteBuffer().getInt(0); + result.getByteBuffer().limit(size); + result.setSize(size); + queryMessageResult.addMessage(result); } } - // ָģ - this.transactionStateService.recoverStateTable(lastExitOK); - - this.recoverTopicQueueTable(); + return queryMessageResult; } - /** - * - * - * @throws IOException - */ - public boolean load() { - boolean result = false; + @Override + public void updateHaMasterAddress(String newAddr) { + this.haService.updateMasterAddress(newAddr); + } - try { - boolean lastExitOK = !this.isTempFileExist(); - log.info("last shutdown " + (lastExitOK ? "normally" : "abnormally")); - // load Commit Log - result = this.commitLog.load(); + @Override + public long now() { + return this.systemClock.now(); + } - // load Consume Queue - result = result && this.loadConsumeQueue(); - // load ģ - result = result && this.transactionStateService.load(); + public CommitLog getCommitLog() { + return commitLog; + } - // load ʱ - result = result && this.scheduleMessageService.load(); - if (result) { - this.storeCheckpoint = new StoreCheckpoint(this.messageStoreConfig.getStoreCheckpoint()); + public MessageExt lookMessageByOffset(long commitLogOffset, int size) { + SelectMapedBufferResult sbr = this.commitLog.getMessage(commitLogOffset, size); + if (null != sbr) { + try { + return MessageDecoder.decode(sbr.getByteBuffer()); + } + finally { + sbr.release(); + } + } - this.indexService.load(lastExitOK); + return null; + } - // Իָ - this.recover(lastExitOK); - log.info("load over, and the max phy offset = " + this.getMaxPhyOffset()); + public ConsumeQueue findConsumeQueue(String topic, int queueId) { + ConcurrentHashMap map = consumeQueueTable.get(topic); + if (null == map) { + ConcurrentHashMap newMap = + new ConcurrentHashMap(128); + ConcurrentHashMap oldMap = consumeQueueTable.putIfAbsent(topic, newMap); + if (oldMap != null) { + map = oldMap; + } + else { + map = newMap; } } - catch (Exception e) { - e.printStackTrace(); + + ConsumeQueue logic = map.get(queueId); + if (null == logic) { + ConsumeQueue newLogic = new ConsumeQueue(// + topic,// + queueId,// + this.getMessageStoreConfig().getStorePathConsumeQueue(),// + this.getMessageStoreConfig().getMapedFileSizeConsumeQueue(),// + this); + ConsumeQueue oldLogic = map.putIfAbsent(queueId, newLogic); + if (oldLogic != null) { + logic = oldLogic; + } + else { + logic = newLogic; + } } - if (!result) { - this.allocateMapedFileService.shutdown(); + return logic; + } + + + private boolean isTheBatchFull(long offsetPy, int sizePy, int maxMsgNums, int bufferTotal, + int messageTotal) { + long maxOffsetPy = this.commitLog.getMaxOffset(); + long memory = + (long) (StoreUtil.TotalPhysicalMemorySize * (this.messageStoreConfig + .getAccessMessageInMemoryMaxRatio() / 100.0)); + + // 第一条消息可以不做限制 + if (0 == bufferTotal || 0 == messageTotal) { + return false; } - return result; + if ((messageTotal + 1) >= maxMsgNums) { + return true; + } + + // 消息在磁盘 + if ((maxOffsetPy - offsetPy) > memory) { + if ((bufferTotal + sizePy) > this.messageStoreConfig.getMaxTransferBytesOnMessageInDisk()) { + return true; + } + + if ((messageTotal + 1) > this.messageStoreConfig.getMaxTransferCountOnMessageInDisk()) { + return true; + } + } + // 消息在内存 + else { + if ((bufferTotal + sizePy) > this.messageStoreConfig.getMaxTransferBytesOnMessageInMemory()) { + return true; + } + + if ((messageTotal + 1) > this.messageStoreConfig.getMaxTransferCountOnMessageInMemory()) { + return true; + } + } + + return false; + } + + + private void deleteFile(final String fileName) { + File file = new File(fileName); + boolean result = file.delete(); + log.info(fileName + (result ? " delete OK" : " delete Failed")); + } + + + /** + * 启动服务后,在存储根目录创建临时文件,类似于 UNIX VI编辑工具 + * + * @throws IOException + */ + private void createTempFile() throws IOException { + String fileName = this.messageStoreConfig.getAbortFile(); + File file = new File(fileName); + MapedFile.ensureDirOK(file.getParent()); + boolean result = file.createNewFile(); + log.info(fileName + (result ? " create OK" : " already exists")); + } + + + private boolean isTempFileExist() { + String fileName = this.messageStoreConfig.getAbortFile(); + File file = new File(fileName); + return file.exists(); } @@ -839,10 +898,10 @@ private boolean loadConsumeQueue() { File dirLogic = new File(this.messageStoreConfig.getStorePathConsumeQueue()); File[] fileTopicList = dirLogic.listFiles(); if (fileTopicList != null) { - // TOPIC + // TOPIC 遍历 for (File fileTopic : fileTopicList) { String topic = fileTopic.getName(); - // TOPIC ¶б + // TOPIC 下队列遍历 File[] fileQueueIdList = fileTopic.listFiles(); if (fileQueueIdList != null) { for (File fileQueueId : fileQueueIdList) { @@ -868,6 +927,11 @@ private boolean loadConsumeQueue() { } + public MessageStoreConfig getMessageStoreConfig() { + return messageStoreConfig; + } + + private void putConsumeQueue(final String topic, final int queueId, final ConsumeQueue consumeQueue) { ConcurrentHashMap map = this.consumeQueueTable.get(topic); if (null == map) { @@ -881,715 +945,813 @@ private void putConsumeQueue(final String topic, final int queueId, final Consum } - /** - * ڴ洢Ŀ¼ʱļ UNIX VI༭ - * - * @throws IOException - */ - private void createTempFile() throws IOException { - String fileName = this.messageStoreConfig.getAbortFile(); - File file = new File(fileName); - MapedFile.ensureDirOK(file.getParent()); - boolean result = file.createNewFile(); - log.info(fileName + (result ? " create OK" : " already exists")); - } - - - private void deleteFile(final String fileName) { - File file = new File(fileName); - boolean result = file.delete(); - log.info(fileName + (result ? " delete OK" : " delete Failed")); - } - - - private boolean isTempFileExist() { - String fileName = this.messageStoreConfig.getAbortFile(); - File file = new File(fileName); - return file.exists(); - } + private void recover(final boolean lastExitOK) { + // 先按照正常流程恢复Consume Queue + this.recoverConsumeQueue(); + // 先按照正常流程恢复Tran Redo Log + this.transactionStateService.getTranRedoLog().recover(); - /** - * 洢 - * - * @throws Exception - */ - public void start() throws Exception { - this.cleanCommitLogService.start(); - this.cleanConsumeQueueService.start(); - this.indexService.start(); - // ڹ캯Ѿstartˡ - // this.dispatchMessageService.start(); - this.flushConsumeQueueService.start(); - this.commitLog.start(); - this.scheduleMessageService.start(); - this.storeStatsService.start(); + // 正常数据恢复 + if (lastExitOK) { + this.commitLog.recoverNormally(); + } + // 异常数据恢复,OS CRASH或者JVM CRASH或者机器掉电 + else { + this.commitLog.recoverAbnormally(); - if (this.reputMessageService != null) { - this.reputMessageService.setReputFromOffset(this.commitLog.getMaxOffset()); - this.reputMessageService.start(); + // 保证消息都能从DispatchService缓冲队列进入到真正的队列 + while (this.dispatchMessageService.hasRemainMessage()) { + try { + Thread.sleep(500); + log.info("waiting dispatching message over"); + } + catch (InterruptedException e) { + e.printStackTrace(); + } + } } - this.haService.start(); + // 恢复事务模块 + this.transactionStateService.recoverStateTable(lastExitOK); - this.createTempFile(); - this.shutdown = false; + this.recoverTopicQueueTable(); } - /** - * رմ洢 - */ - public void shutdown() { - if (!this.shutdown) { - this.shutdown = true; - - try { - // ȴֹͣ - Thread.sleep(1000 * 3); - } - catch (InterruptedException e) { - log.error("shutdown Exception, ", e); + private void recoverTopicQueueTable() { + HashMap table = new HashMap(1024); + long minPhyOffset = this.commitLog.getMinOffset(); + for (ConcurrentHashMap maps : this.consumeQueueTable.values()) { + for (ConsumeQueue logic : maps.values()) { + // 恢复写入消息时,记录的队列offset + String key = logic.getTopic() + "-" + logic.getQueueId(); + table.put(key, logic.getMaxOffsetInQuque()); + // 恢复每个队列的最小offset + logic.correctMinOffset(minPhyOffset); } + } - this.scheduleMessageService.shutdown(); - this.haService.shutdown(); + this.commitLog.setTopicQueueTable(table); + } - this.storeStatsService.shutdown(); - this.cleanCommitLogService.shutdown(); - this.cleanConsumeQueueService.shutdown(); - this.dispatchMessageService.shutdown(); - this.indexService.shutdown(); - this.flushConsumeQueueService.shutdown(); - this.commitLog.shutdown(); - this.allocateMapedFileService.shutdown(); - if (this.reputMessageService != null) { - this.reputMessageService.shutdown(); + + private void recoverConsumeQueue() { + for (ConcurrentHashMap maps : this.consumeQueueTable.values()) { + for (ConsumeQueue logic : maps.values()) { + logic.recover(); } - this.storeCheckpoint.flush(); - this.storeCheckpoint.shutdown(); - this.deleteFile(this.messageStoreConfig.getAbortFile()); } } - public PutMessageResult putMessage(MessageExtBrokerInner msg) { - if (this.shutdown) { - log.warn("message store has shutdown, so putMessage is forbidden"); - return new PutMessageResult(PutMessageStatus.SERVICE_NOT_AVAILABLE, null); - } + public void putMessagePostionInfo(String topic, int queueId, long offset, int size, long tagsCode, + long storeTimestamp, long logicOffset) { + ConsumeQueue cq = this.findConsumeQueue(topic, queueId); + cq.putMessagePostionInfoWrapper(offset, size, tagsCode, storeTimestamp, logicOffset); + } - if (BrokerRole.SLAVE == this.messageStoreConfig.getBrokerRole()) { - long value = this.printTimes.getAndIncrement(); - if ((value % 50000) == 0) { - log.warn("message store is slave mode, so putMessage is forbidden "); - } - return new PutMessageResult(PutMessageStatus.SERVICE_NOT_AVAILABLE, null); - } + public void putDispatchRequest(final DispatchRequest dispatchRequest) { + this.dispatchMessageService.putRequest(dispatchRequest); + } - if (!this.runningFlags.isWriteable()) { - long value = this.printTimes.getAndIncrement(); - if ((value % 50000) == 0) { - log.warn("message store is not writeable, so putMessage is forbidden " - + this.runningFlags.getFlagBits()); - } - return new PutMessageResult(PutMessageStatus.SERVICE_NOT_AVAILABLE, null); - } - else { - this.printTimes.set(0); - } + public DispatchMessageService getDispatchMessageService() { + return dispatchMessageService; + } - // message topicУ - if (msg.getTopic().length() > Byte.MAX_VALUE) { - log.warn("putMessage message topic length too long " + msg.getTopic().length()); - return new PutMessageResult(PutMessageStatus.MESSAGE_ILLEGAL, null); - } - // message propertiesУ - if (msg.getPropertiesString() != null && msg.getPropertiesString().length() > Short.MAX_VALUE) { - log.warn("putMessage message properties length too long " + msg.getPropertiesString().length()); - return new PutMessageResult(PutMessageStatus.MESSAGE_ILLEGAL, null); - } + public AllocateMapedFileService getAllocateMapedFileService() { + return allocateMapedFileService; + } - long beginTime = this.getSystemClock().now(); - PutMessageResult result = this.commitLog.putMessage(msg); - // ͳ - long eclipseTime = this.getSystemClock().now() - beginTime; - if (eclipseTime > 1000) { - log.warn("putMessage not in lock eclipse time(ms) " + eclipseTime); - } - this.storeStatsService.setPutMessageEntireTimeMax(eclipseTime); - this.storeStatsService.getPutMessageTimesTotal().incrementAndGet(); - if (null == result || !result.isOk()) { - this.storeStatsService.getPutMessageFailedTimes().incrementAndGet(); - } + public StoreStatsService getStoreStatsService() { + return storeStatsService; + } - return result; + + public RunningFlags getAccessRights() { + return runningFlags; } - private boolean isTheBatchFull(long offsetPy, int sizePy, int maxMsgNums, int bufferTotal, int messageTotal) { - long maxOffsetPy = this.commitLog.getMaxOffset(); - long memory = - (long) (MixAll.TotalPhysicalMemorySize * (this.messageStoreConfig - .getAccessMessageInMemoryMaxRatio() / 100.0)); + public ConcurrentHashMap> getConsumeQueueTable() { + return consumeQueueTable; + } - // һϢԲ - if (0 == bufferTotal || 0 == messageTotal) { - return false; - } - if ((messageTotal + 1) >= maxMsgNums) { - return true; - } + public StoreCheckpoint getStoreCheckpoint() { + return storeCheckpoint; + } - // Ϣڴ - if ((maxOffsetPy - offsetPy) > memory) { - if ((bufferTotal + sizePy) > this.messageStoreConfig.getMaxTransferBytesOnMessageInDisk()) { - return true; - } - if ((messageTotal + 1) > this.messageStoreConfig.getMaxTransferCountOnMessageInDisk()) { - return true; - } - } - // Ϣڴ - else { - if ((bufferTotal + sizePy) > this.messageStoreConfig.getMaxTransferBytesOnMessageInMemory()) { - return true; - } + public HAService getHaService() { + return haService; + } - if ((messageTotal + 1) > this.messageStoreConfig.getMaxTransferCountOnMessageInMemory()) { - return true; - } - } - return false; + public ScheduleMessageService getScheduleMessageService() { + return scheduleMessageService; } - public GetMessageResult getMessage(final String topic, final int queueId, final long offset, - final int maxMsgNums, final SubscriptionData subscriptionData) { - if (this.shutdown) { - log.warn("message store has shutdown, so getMessage is forbidden"); - return null; - } + public TransactionStateService getTransactionStateService() { + return transactionStateService; + } - if (!this.runningFlags.isReadable()) { - log.warn("message store is not readable, so getMessage is forbidden " + this.runningFlags.getFlagBits()); - return null; - } - long beginTime = this.getSystemClock().now(); + public RunningFlags getRunningFlags() { + return runningFlags; + } - // öٱȡϢ - GetMessageStatus status = GetMessageStatus.NO_MESSAGE_IN_QUEUE; - // ˺󣬷һοʼOffset - long nextBeginOffset = offset; - // ߼еСOffset - long minOffset = 0; - // ߼еOffset - long maxOffset = 0; - GetMessageResult getResult = new GetMessageResult(); + public TransactionCheckExecuter getTransactionCheckExecuter() { + return transactionCheckExecuter; + } - ConsumeQueue consumeQueue = findConsumeQueue(topic, queueId); - if (consumeQueue != null) { - minOffset = consumeQueue.getMinOffsetInQuque(); - maxOffset = consumeQueue.getMaxOffsetInQuque(); + /** + * 清理物理文件服务 + */ + class CleanCommitLogService extends ServiceThread { + // 手工触发一次最多删除次数 + private final static int MaxManualDeleteFileTimes = 20; + // 磁盘空间警戒水位,超过,则停止接收新消息(出于保护自身目的) + private final double DiskSpaceWarningLevelRatio = Double.parseDouble(System.getProperty( + "rocketmq.broker.diskSpaceWarningLevelRatio", "0.90")); + // 磁盘空间强制删除文件水位 + private final double DiskSpaceCleanForciblyRatio = Double.parseDouble(System.getProperty( + "rocketmq.broker.diskSpaceCleanForciblyRatio", "0.85")); + private long lastRedeleteTimestamp = 0; + // 手工触发删除消息 + private volatile int manualDeleteFileSeveralTimes = 0; + // 立刻开始强制删除文件 + private volatile boolean cleanImmediately = false; - if (maxOffset == 0) { - status = GetMessageStatus.NO_MESSAGE_IN_QUEUE; - nextBeginOffset = 0; - } - else if (offset < minOffset) { - status = GetMessageStatus.OFFSET_TOO_SMALL; - nextBeginOffset = minOffset; - } - else if (offset == maxOffset) { - status = GetMessageStatus.OFFSET_OVERFLOW_ONE; - nextBeginOffset = offset; + + public void excuteDeleteFilesManualy() { + this.manualDeleteFileSeveralTimes = MaxManualDeleteFileTimes; + DefaultMessageStore.log.info("excuteDeleteFilesManualy was invoked"); + } + + + public void run() { + DefaultMessageStore.log.info(this.getServiceName() + " service started"); + int cleanResourceInterval = + DefaultMessageStore.this.getMessageStoreConfig().getCleanResourceInterval(); + while (!this.isStoped()) { + try { + this.waitForRunning(cleanResourceInterval); + + this.deleteExpiredFiles(); + + this.redeleteHangedFile(); + } + catch (Exception e) { + DefaultMessageStore.log.warn(this.getServiceName() + " service has exception. ", e); + } } - else if (offset > maxOffset) { - status = GetMessageStatus.OFFSET_OVERFLOW_BADLY; - nextBeginOffset = maxOffset; + + DefaultMessageStore.log.info(this.getServiceName() + " service end"); + } + + + @Override + public String getServiceName() { + return CleanCommitLogService.class.getSimpleName(); + } + + + /** + * 最前面的文件有可能Hang住,定期检查一下 + */ + private void redeleteHangedFile() { + int interval = DefaultMessageStore.this.getMessageStoreConfig().getRedeleteHangedFileInterval(); + long currentTimestamp = System.currentTimeMillis(); + if ((currentTimestamp - this.lastRedeleteTimestamp) > interval) { + this.lastRedeleteTimestamp = currentTimestamp; + int destroyMapedFileIntervalForcibly = + DefaultMessageStore.this.getMessageStoreConfig() + .getDestroyMapedFileIntervalForcibly(); + if (DefaultMessageStore.this.commitLog.retryDeleteFirstFile(destroyMapedFileIntervalForcibly)) { + DefaultMessageStore.this.cleanConsumeQueueService.wakeup(); + } } - else { - SelectMapedBufferResult bufferConsumeQueue = consumeQueue.getIndexBuffer(offset); - if (bufferConsumeQueue != null) { - try { - status = GetMessageStatus.NO_MATCHED_MESSAGE; + } - long nextPhyFileStartOffset = Long.MIN_VALUE; - long maxPhyOffsetPulling = 0; - int i = 0; - final int MaxFilterMessageCount = 16000; - for (; i < bufferConsumeQueue.getSize() && i < MaxFilterMessageCount; i += - ConsumeQueue.CQStoreUnitSize) { - long offsetPy = bufferConsumeQueue.getByteBuffer().getLong(); - int sizePy = bufferConsumeQueue.getByteBuffer().getInt(); - long tagsCode = bufferConsumeQueue.getByteBuffer().getLong(); + private void deleteExpiredFiles() { + int deleteCount = 0; + long fileReservedTime = DefaultMessageStore.this.getMessageStoreConfig().getFileReservedTime(); + int deletePhysicFilesInterval = + DefaultMessageStore.this.getMessageStoreConfig().getDeleteCommitLogFilesInterval(); + int destroyMapedFileIntervalForcibly = + DefaultMessageStore.this.getMessageStoreConfig().getDestroyMapedFileIntervalForcibly(); - maxPhyOffsetPulling = offsetPy; + boolean timeup = this.isTimeToDelete(); + boolean spacefull = this.isSpaceToDelete(); + boolean manualDelete = this.manualDeleteFileSeveralTimes > 0; - // ˵ļڱɾ - if (nextPhyFileStartOffset != Long.MIN_VALUE) { - if (offsetPy < nextPhyFileStartOffset) - continue; - } + // 删除物理队列文件 + if (timeup || spacefull || manualDelete) { + log.info("begin to delete before " + fileReservedTime + " hours file. timeup: " + timeup + + " spacefull: " + spacefull + " manualDeleteFileSeveralTimes: " + + this.manualDeleteFileSeveralTimes); - // Ϣﵽ - if (this.isTheBatchFull(offsetPy, sizePy, maxMsgNums, getResult.getBufferTotalSize(), - getResult.getMessageCount())) { - break; - } + if (manualDelete) + this.manualDeleteFileSeveralTimes--; - // Ϣ - if (this.messageFilter.isMessageMatched(subscriptionData, tagsCode)) { - SelectMapedBufferResult selectResult = this.commitLog.getMessage(offsetPy, sizePy); - if (selectResult != null) { - this.storeStatsService.getGetMessageTransferedMsgCount().incrementAndGet(); - getResult.addMessage(selectResult); - status = GetMessageStatus.FOUND; - nextPhyFileStartOffset = Long.MIN_VALUE; - } - else { - if (getResult.getBufferTotalSize() == 0) { - status = GetMessageStatus.MESSAGE_WAS_REMOVING; - } + // 小时转化成毫秒 + fileReservedTime *= 60 * 60 * 1000; - // ļڱɾ - nextPhyFileStartOffset = this.commitLog.rollNextFile(offsetPy); - } - } - else { - if (getResult.getBufferTotalSize() == 0) { - status = GetMessageStatus.NO_MATCHED_MESSAGE; - } + // 是否立刻强制删除文件 + boolean cleanAtOnce = + DefaultMessageStore.this.getMessageStoreConfig().isCleanFileForciblyEnable() + && this.cleanImmediately; - if (log.isDebugEnabled()) { - log.debug("message type not matched, client: " + subscriptionData - + " server: " + tagsCode); - } - } - } + deleteCount = + DefaultMessageStore.this.commitLog.deleteExpiredFile(fileReservedTime, + deletePhysicFilesInterval, destroyMapedFileIntervalForcibly, cleanAtOnce); + if (deleteCount > 0) { + DefaultMessageStore.this.cleanConsumeQueueService.wakeup(); + } + // 危险情况:磁盘满了,但是又无法删除文件 + else if (spacefull) { + log.warn("disk space will be full soon, but delete file failed."); + } + } + } - nextBeginOffset = offset + (i / ConsumeQueue.CQStoreUnitSize); - long diff = this.getMaxPhyOffset() - maxPhyOffsetPulling; - long memory = - (long) (MixAll.TotalPhysicalMemorySize * (this.messageStoreConfig - .getAccessMessageInMemoryMaxRatio() / 100.0)); - getResult.setSuggestPullingFromSlave(diff > memory); + /** + * 是否可以删除文件,空间是否满足 + */ + private boolean isSpaceToDelete() { + double ratio = + DefaultMessageStore.this.getMessageStoreConfig().getDiskMaxUsedSpaceRatio() / 100.0; + + cleanImmediately = false; + + // 检测物理文件磁盘空间 + { + String storePathPhysic = + DefaultMessageStore.this.getMessageStoreConfig().getStorePathCommitLog(); + double physicRatio = UtilAll.getDiskPartitionSpaceUsedPercent(storePathPhysic); + if (physicRatio > DiskSpaceWarningLevelRatio) { + boolean diskok = DefaultMessageStore.this.runningFlags.getAndMakeDiskFull(); + if (diskok) { + DefaultMessageStore.log.error("physic disk maybe full soon " + physicRatio + + ", so mark disk full"); + System.gc(); } - finally { - // ͷԴ - bufferConsumeQueue.release(); + + cleanImmediately = true; + } + else if (physicRatio > DiskSpaceCleanForciblyRatio) { + cleanImmediately = true; + } + else { + boolean diskok = DefaultMessageStore.this.runningFlags.getAndMakeDiskOK(); + if (!diskok) { + DefaultMessageStore.log.info("physic disk space OK " + physicRatio + + ", so mark disk ok"); + } + } + + if (physicRatio < 0 || physicRatio > ratio) { + DefaultMessageStore.log.info("physic disk maybe full soon, so reclaim space, " + + physicRatio); + return true; + } + } + + // 检测逻辑文件磁盘空间 + { + String storePathLogics = + DefaultMessageStore.this.getMessageStoreConfig().getStorePathConsumeQueue(); + double logicsRatio = UtilAll.getDiskPartitionSpaceUsedPercent(storePathLogics); + if (logicsRatio > DiskSpaceWarningLevelRatio) { + boolean diskok = DefaultMessageStore.this.runningFlags.getAndMakeDiskFull(); + if (diskok) { + DefaultMessageStore.log.error("logics disk maybe full soon " + logicsRatio + + ", so mark disk full"); + System.gc(); } + + cleanImmediately = true; + } + else if (logicsRatio > DiskSpaceCleanForciblyRatio) { + cleanImmediately = true; } else { - status = GetMessageStatus.OFFSET_FOUND_NULL; - nextBeginOffset = consumeQueue.rollNextFile(offset); - log.warn("consumer request topic: " + topic + "offset: " + offset + " minOffset: " + minOffset - + " maxOffset: " + maxOffset + ", but access logic queue failed."); + boolean diskok = DefaultMessageStore.this.runningFlags.getAndMakeDiskOK(); + if (!diskok) { + DefaultMessageStore.log.info("logics disk space OK " + logicsRatio + + ", so mark disk ok"); + } + } + + if (logicsRatio < 0 || logicsRatio > ratio) { + DefaultMessageStore.log.info("logics disk maybe full soon, so reclaim space, " + + logicsRatio); + return true; } } - } - // ĶIdû - else { - status = GetMessageStatus.NO_MATCHED_LOGIC_QUEUE; - nextBeginOffset = 0; + + return false; } - if (GetMessageStatus.FOUND == status) { - this.storeStatsService.getGetMessageTimesTotalFound().incrementAndGet(); + + /** + * 是否可以删除文件,时间是否满足 + */ + private boolean isTimeToDelete() { + String when = DefaultMessageStore.this.getMessageStoreConfig().getDeleteWhen(); + if (UtilAll.isItTimeToDo(when)) { + DefaultMessageStore.log.info("it's time to reclaim disk space, " + when); + return true; + } + + return false; } - else { - this.storeStatsService.getGetMessageTimesTotalMiss().incrementAndGet(); + + + public int getManualDeleteFileSeveralTimes() { + return manualDeleteFileSeveralTimes; } - long eclipseTime = this.getSystemClock().now() - beginTime; - this.storeStatsService.setGetMessageEntireTimeMax(eclipseTime); - getResult.setStatus(status); - getResult.setNextBeginOffset(nextBeginOffset); - getResult.setMaxOffset(maxOffset); - getResult.setMinOffset(minOffset); - return getResult; + + public void setManualDeleteFileSeveralTimes(int manualDeleteFileSeveralTimes) { + this.manualDeleteFileSeveralTimes = manualDeleteFileSeveralTimes; + } } + /** + * 清理逻辑文件服务 + */ + class CleanConsumeQueueService extends ServiceThread { + private long lastPhysicalMinOffset = 0; - public ConsumeQueue findConsumeQueue(String topic, int queueId) { - ConcurrentHashMap map = consumeQueueTable.get(topic); - if (null == map) { - ConcurrentHashMap newMap = new ConcurrentHashMap(128); - ConcurrentHashMap oldMap = consumeQueueTable.putIfAbsent(topic, newMap); - if (oldMap != null) { - map = oldMap; - } - else { - map = newMap; - } - } - ConsumeQueue logic = map.get(queueId); - if (null == logic) { - ConsumeQueue newLogic = new ConsumeQueue(// - topic,// - queueId,// - this.getMessageStoreConfig().getStorePathConsumeQueue(),// - this.getMessageStoreConfig().getMapedFileSizeConsumeQueue(),// - this); - ConsumeQueue oldLogic = map.putIfAbsent(queueId, newLogic); - if (oldLogic != null) { - logic = oldLogic; - } - else { - logic = newLogic; - } - } + private void deleteExpiredFiles() { + int deleteLogicsFilesInterval = + DefaultMessageStore.this.getMessageStoreConfig().getDeleteConsumeQueueFilesInterval(); - return logic; - } + long minOffset = DefaultMessageStore.this.commitLog.getMinOffset(); + if (minOffset > this.lastPhysicalMinOffset) { + this.lastPhysicalMinOffset = minOffset; + // 删除逻辑队列文件 + ConcurrentHashMap> tables = + DefaultMessageStore.this.consumeQueueTable; - public void putMessagePostionInfo(String topic, int queueId, long offset, int size, long tagsCode, - long storeTimestamp, long logicOffset) { - ConsumeQueue cq = this.findConsumeQueue(topic, queueId); - cq.putMessagePostionInfoWrapper(offset, size, tagsCode, storeTimestamp, logicOffset); - } + for (ConcurrentHashMap maps : tables.values()) { + for (ConsumeQueue logic : maps.values()) { + int deleteCount = logic.deleteExpiredFile(minOffset); + if (deleteCount > 0 && deleteLogicsFilesInterval > 0) { + try { + Thread.sleep(deleteLogicsFilesInterval); + } + catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + } - public void putDispatchRequest(final DispatchRequest dispatchRequest) { - this.dispatchMessageService.putRequest(dispatchRequest); - } + // 删除日志RedoLog + DefaultMessageStore.this.transactionStateService.getTranRedoLog() + .deleteExpiredFile(minOffset); + // 删除日志StateTable + DefaultMessageStore.this.transactionStateService.deleteExpiredStateFile(minOffset); + // 删除索引 + DefaultMessageStore.this.indexService.deleteExpiredFile(minOffset); + } + } - public MessageStoreConfig getMessageStoreConfig() { - return messageStoreConfig; - } + public void run() { + DefaultMessageStore.log.info(this.getServiceName() + " service started"); + int cleanResourceInterval = + DefaultMessageStore.this.getMessageStoreConfig().getCleanResourceInterval(); + while (!this.isStoped()) { + try { + this.deleteExpiredFiles(); + this.waitForRunning(cleanResourceInterval); + } + catch (Exception e) { + DefaultMessageStore.log.warn(this.getServiceName() + " service has exception. ", e); + } + } - public CommitLog getCommitLog() { - return commitLog; - } + DefaultMessageStore.log.info(this.getServiceName() + " service end"); + } - public DispatchMessageService getDispatchMessageService() { - return dispatchMessageService; + @Override + public String getServiceName() { + return CleanConsumeQueueService.class.getSimpleName(); + } } - /** - * صǵǰЧOffsetOffsetжӦϢ + * 逻辑队列刷盘服务 */ - public long getMaxOffsetInQuque(String topic, int queueId) { - ConsumeQueue logic = this.findConsumeQueue(topic, queueId); - if (logic != null) { - long offset = logic.getMaxOffsetInQuque(); - // - // if (offset > 0) - // offset -= 1; - return offset; - } + class FlushConsumeQueueService extends ServiceThread { + private static final int RetryTimesOver = 3; + private long lastFlushTimestamp = 0; - return 0; - } + private void doFlush(int retryTimes) { + /** + * 变量含义:如果大于0,则标识这次刷盘必须刷多少个page,如果=0,则有多少刷多少 + */ + int flushConsumeQueueLeastPages = + DefaultMessageStore.this.getMessageStoreConfig().getFlushConsumeQueueLeastPages(); - public long getMinOffsetInQuque(String topic, int queueId) { - ConsumeQueue logic = this.findConsumeQueue(topic, queueId); - if (logic != null) { - return logic.getMinOffsetInQuque(); - } + if (retryTimes == RetryTimesOver) { + flushConsumeQueueLeastPages = 0; + } - return -1; - } + long logicsMsgTimestamp = 0; + // 定时刷盘 + int flushConsumeQueueThoroughInterval = + DefaultMessageStore.this.getMessageStoreConfig().getFlushConsumeQueueThoroughInterval(); + long currentTimeMillis = System.currentTimeMillis(); + if (currentTimeMillis >= (this.lastFlushTimestamp + flushConsumeQueueThoroughInterval)) { + this.lastFlushTimestamp = currentTimeMillis; + flushConsumeQueueLeastPages = 0; + logicsMsgTimestamp = DefaultMessageStore.this.getStoreCheckpoint().getLogicsMsgTimestamp(); + } - public AllocateMapedFileService getAllocateMapedFileService() { - return allocateMapedFileService; - } + ConcurrentHashMap> tables = + DefaultMessageStore.this.consumeQueueTable; + for (ConcurrentHashMap maps : tables.values()) { + for (ConsumeQueue cq : maps.values()) { + boolean result = false; + for (int i = 0; i < retryTimes && !result; i++) { + result = cq.commit(flushConsumeQueueLeastPages); + } + } + } - public StoreStatsService getStoreStatsService() { - return storeStatsService; - } + // 事务Redolog + DefaultMessageStore.this.transactionStateService.getTranRedoLog().commit( + flushConsumeQueueLeastPages); + if (0 == flushConsumeQueueLeastPages) { + if (logicsMsgTimestamp > 0) { + DefaultMessageStore.this.getStoreCheckpoint().setLogicsMsgTimestamp(logicsMsgTimestamp); + } + DefaultMessageStore.this.getStoreCheckpoint().flush(); + } + } - public String getRunningDataInfo() { - return this.storeStatsService.toString(); - } + public void run() { + DefaultMessageStore.log.info(this.getServiceName() + " service started"); - public RunningFlags getAccessRights() { - return runningFlags; - } + while (!this.isStoped()) { + try { + int interval = + DefaultMessageStore.this.getMessageStoreConfig().getFlushIntervalConsumeQueue(); + this.waitForRunning(interval); + this.doFlush(1); + } + catch (Exception e) { + DefaultMessageStore.log.warn(this.getServiceName() + " service has exception. ", e); + } + } + // 正常shutdown时,要保证全部刷盘才退出 + this.doFlush(RetryTimesOver); - public long getOffsetInQueueByTime(String topic, int queueId, long timestamp) { - ConsumeQueue logic = this.findConsumeQueue(topic, queueId); - if (logic != null) { - return logic.getOffsetInQueueByTime(timestamp); + DefaultMessageStore.log.info(this.getServiceName() + " service end"); } - return 0; - } - - public MessageExt lookMessageByOffset(long phyOffset) { - SelectMapedBufferResult sbr = this.commitLog.getMessage(phyOffset, 4); - if (null != sbr) { - try { - // 1 TOTALSIZE - int size = sbr.getByteBuffer().getInt(); - return lookMessageByOffset(phyOffset, size); - } - finally { - sbr.release(); - } + @Override + public String getServiceName() { + return FlushConsumeQueueService.class.getSimpleName(); } - return null; + + @Override + public long getJointime() { + return 1000 * 60; + } } + /** + * 分发消息索引服务 + */ + class DispatchMessageService extends ServiceThread { + private volatile List requestsWrite; + private volatile List requestsRead; + - public MessageExt lookMessageByOffset(long phyOffset, int size) { - SelectMapedBufferResult sbr = this.commitLog.getMessage(phyOffset, size); - if (null != sbr) { - try { - return MessageDecoder.decode(sbr.getByteBuffer()); - } - finally { - sbr.release(); - } + public DispatchMessageService(int putMsgIndexHightWater) { + putMsgIndexHightWater *= 1.5; + this.requestsWrite = new ArrayList(putMsgIndexHightWater); + this.requestsRead = new ArrayList(putMsgIndexHightWater); } - return null; - } + public boolean hasRemainMessage() { + List reqs = this.requestsWrite; + if (reqs != null && !reqs.isEmpty()) { + return true; + } - public ConcurrentHashMap> getConsumeQueueTable() { - return consumeQueueTable; - } + reqs = this.requestsRead; + if (reqs != null && !reqs.isEmpty()) { + return true; + } + return false; + } - public StoreCheckpoint getStoreCheckpoint() { - return storeCheckpoint; - } + public void putRequest(final DispatchRequest dispatchRequest) { + int requestsWriteSize = 0; + int putMsgIndexHightWater = + DefaultMessageStore.this.getMessageStoreConfig().getPutMsgIndexHightWater(); + synchronized (this) { + this.requestsWrite.add(dispatchRequest); + requestsWriteSize = this.requestsWrite.size(); + if (!this.hasNotified) { + this.hasNotified = true; + this.notify(); + } + } - private void recoverConsumeQueue() { - for (ConcurrentHashMap maps : this.consumeQueueTable.values()) { - for (ConsumeQueue logic : maps.values()) { - logic.recover(); + DefaultMessageStore.this.getStoreStatsService().setDispatchMaxBuffer(requestsWriteSize); + + // 这里主动做流控,防止CommitLog写入太快,导致消费队列被冲垮 + if (requestsWriteSize > putMsgIndexHightWater) { + try { + if (log.isDebugEnabled()) { + log.debug("Message index buffer size " + requestsWriteSize + " > high water " + + putMsgIndexHightWater); + } + + Thread.sleep(1); + } + catch (InterruptedException e) { + e.printStackTrace(); + } } } - } - private void recoverTopicQueueTable() { - HashMap table = new HashMap(1024); - long minPhyOffset = this.commitLog.getMinOffset(); - for (ConcurrentHashMap maps : this.consumeQueueTable.values()) { - for (ConsumeQueue logic : maps.values()) { - // ָдϢʱ¼Ķoffset - String key = logic.getTopic() + "-" + logic.getQueueId(); - table.put(key, logic.getMaxOffsetInQuque()); - // ָÿеСoffset - logic.correctMinOffset(minPhyOffset); - } + private void swapRequests() { + List tmp = this.requestsWrite; + this.requestsWrite = this.requestsRead; + this.requestsRead = tmp; } - this.commitLog.setTopicQueueTable(table); - } + private void doDispatch() { + if (!this.requestsRead.isEmpty()) { + for (DispatchRequest req : this.requestsRead) { + + final int tranType = MessageSysFlag.getTransactionValue(req.getSysFlag()); + // 1、分发消息位置信息到ConsumeQueue + switch (tranType) { + case MessageSysFlag.TransactionNotType: + case MessageSysFlag.TransactionCommitType: + // 将请求发到具体的Consume Queue + DefaultMessageStore.this.putMessagePostionInfo(req.getTopic(), req.getQueueId(), + req.getCommitLogOffset(), req.getMsgSize(), req.getTagsCode(), + req.getStoreTimestamp(), req.getConsumeQueueOffset()); + break; + case MessageSysFlag.TransactionPreparedType: + case MessageSysFlag.TransactionRollbackType: + break; + } + + // 2、更新Transaction State Table + if (req.getProducerGroup() != null) { + switch (tranType) { + case MessageSysFlag.TransactionNotType: + break; + case MessageSysFlag.TransactionPreparedType: + // 将Prepared事务记录下来 + DefaultMessageStore.this.getTransactionStateService().appendPreparedTransaction(// + req.getCommitLogOffset(),// + req.getMsgSize(),// + (int) (req.getStoreTimestamp() / 1000),// + req.getProducerGroup().hashCode()); + break; + case MessageSysFlag.TransactionCommitType: + case MessageSysFlag.TransactionRollbackType: + DefaultMessageStore.this.getTransactionStateService().updateTransactionState(// + req.getTranStateTableOffset(),// + req.getPreparedTransactionOffset(),// + req.getProducerGroup().hashCode(),// + tranType// + ); + break; + } + } + // 3、记录Transaction Redo Log + switch (tranType) { + case MessageSysFlag.TransactionNotType: + break; + case MessageSysFlag.TransactionPreparedType: + // 记录redolog + DefaultMessageStore.this.getTransactionStateService().getTranRedoLog() + .putMessagePostionInfoWrapper(// + req.getCommitLogOffset(),// + req.getMsgSize(),// + TransactionStateService.PreparedMessageTagsCode,// + req.getStoreTimestamp(),// + 0L// + ); + break; + case MessageSysFlag.TransactionCommitType: + case MessageSysFlag.TransactionRollbackType: + // 记录redolog + DefaultMessageStore.this.getTransactionStateService().getTranRedoLog() + .putMessagePostionInfoWrapper(// + req.getCommitLogOffset(),// + req.getMsgSize(),// + req.getPreparedTransactionOffset(),// + req.getStoreTimestamp(),// + 0L// + ); + break; + } + } + + if (DefaultMessageStore.this.getMessageStoreConfig().isMessageIndexEnable()) { + DefaultMessageStore.this.indexService.putRequest(this.requestsRead.toArray()); + } - public void destroyLogics() { - for (ConcurrentHashMap maps : this.consumeQueueTable.values()) { - for (ConsumeQueue logic : maps.values()) { - logic.destroy(); + this.requestsRead.clear(); } } - } - - - public void destroy() { - this.destroyLogics(); - this.commitLog.destroy(); - this.indexService.destroy(); - this.deleteFile(this.messageStoreConfig.getAbortFile()); - this.deleteFile(this.messageStoreConfig.getStoreCheckpoint()); - } - - @Override - public long getMaxPhyOffset() { - return this.commitLog.getMaxOffset(); - } + public void run() { + DefaultMessageStore.log.info(this.getServiceName() + " service started"); - @Override - public long getEarliestMessageTime(String topic, int queueId) { - ConsumeQueue logicQueue = this.findConsumeQueue(topic, queueId); - if (logicQueue != null) { - long minLogicOffset = logicQueue.getMinLogicOffset(); - - SelectMapedBufferResult result = - logicQueue.getIndexBuffer(minLogicOffset / ConsumeQueue.CQStoreUnitSize); - if (result != null) { + while (!this.isStoped()) { try { - final long phyOffset = result.getByteBuffer().getLong(); - final int size = result.getByteBuffer().getInt(); - long storeTime = this.getCommitLog().pickupStoretimestamp(phyOffset, size); - return storeTime; + this.waitForRunning(0); + this.doDispatch(); } catch (Exception e) { - } - finally { - result.release(); + DefaultMessageStore.log.warn(this.getServiceName() + " service has exception. ", e); } } - } - - return -1; - } + // 在正常shutdown情况下,要保证所有消息都dispatch + try { + Thread.sleep(5 * 1000); + } + catch (InterruptedException e) { + DefaultMessageStore.log.warn("DispatchMessageService Exception, ", e); + } - @Override - public long getMessageTotalInQueue(String topic, int queueId) { - ConsumeQueue logicQueue = this.findConsumeQueue(topic, queueId); - if (logicQueue != null) { - return logicQueue.getMessageTotalInQueue(); - } - - return -1; - } + synchronized (this) { + this.swapRequests(); + } + this.doDispatch(); - @Override - public SelectMapedBufferResult getCommitLogData(final long offset) { - if (this.shutdown) { - log.warn("message store has shutdown, so getPhyQueueData is forbidden"); - return null; + DefaultMessageStore.log.info(this.getServiceName() + " service end"); } - return this.commitLog.getData(offset); - } - - @Override - public boolean appendToCommitLog(long startOffset, byte[] data) { - if (this.shutdown) { - log.warn("message store has shutdown, so appendToPhyQueue is forbidden"); - return false; + @Override + protected void onWaitEnd() { + this.swapRequests(); } - boolean result = this.commitLog.appendData(startOffset, data); - if (result) { - this.reputMessageService.wakeup(); - } - else { - log.error("appendToPhyQueue failed " + startOffset + " " + data.length); - } - return result; + @Override + public String getServiceName() { + return DispatchMessageService.class.getSimpleName(); + } } + /** + * SLAVE: 从物理队列Load消息,并分发到各个逻辑队列 + */ + class ReputMessageService extends ServiceThread { + // 从这里开始解析物理队列数据,并分发到逻辑队列 + private volatile long reputFromOffset = 0; - public SystemClock getSystemClock() { - return systemClock; - } + public long getReputFromOffset() { + return reputFromOffset; + } - @Override - public void excuteDeleteFilesManualy() { - this.cleanCommitLogService.excuteDeleteFilesManualy(); - } + public void setReputFromOffset(long reputFromOffset) { + this.reputFromOffset = reputFromOffset; + } - @Override - public QueryMessageResult queryMessage(String topic, String key, int maxNum, long begin, long end) { - QueryOffsetResult queryOffsetResult = this.indexService.queryOffset(topic, key, maxNum, begin, end); - QueryMessageResult queryMessageResult = new QueryMessageResult(); - queryMessageResult.setIndexLastUpdatePhyoffset(queryOffsetResult.getIndexLastUpdatePhyoffset()); - queryMessageResult.setIndexLastUpdateTimestamp(queryOffsetResult.getIndexLastUpdateTimestamp()); + private void doReput() { + for (boolean doNext = true; doNext;) { + SelectMapedBufferResult result = DefaultMessageStore.this.commitLog.getData(reputFromOffset); + if (result != null) { + try { + for (int readSize = 0; readSize < result.getSize() && doNext;) { + DispatchRequest dispatchRequest = + DefaultMessageStore.this.commitLog.checkMessageAndReturnSize( + result.getByteBuffer(), false, false); + int size = dispatchRequest.getMsgSize(); + // 正常数据 + if (size > 0) { + DefaultMessageStore.this.putDispatchRequest(dispatchRequest); - for (Long offset : queryOffsetResult.getPhyOffsets()) { - SelectMapedBufferResult result = this.commitLog.getData(offset, false); - if (result != null) { - int size = result.getByteBuffer().getInt(0); - result.getByteBuffer().limit(size); - queryMessageResult.addMessage(result); + this.reputFromOffset += size; + readSize += size; + DefaultMessageStore.this.storeStatsService + .getSinglePutMessageTopicTimesTotal(dispatchRequest.getTopic()) + .incrementAndGet(); + DefaultMessageStore.this.storeStatsService.getSinglePutMessageTopicSizeTotal( + dispatchRequest.getTopic()).addAndGet(dispatchRequest.getMsgSize()); + } + // 文件中间读到错误 + else if (size == -1) { + doNext = false; + } + // 走到文件末尾,切换至下一个文件 + else if (size == 0) { + this.reputFromOffset = + DefaultMessageStore.this.commitLog.rollNextFile(this.reputFromOffset); + readSize = result.getSize(); + } + } + } + finally { + result.release(); + } + } + else { + doNext = false; + } } } - return queryMessageResult; - } - - - public HAService getHaService() { - return haService; - } + @Override + public void run() { + DefaultMessageStore.log.info(this.getServiceName() + " service started"); - @Override - public void updateMasterAddress(String newAddr) { - this.haService.updateMasterAddress(newAddr); - } + while (!this.isStoped()) { + try { + this.waitForRunning(1000); + this.doReput(); + } + catch (Exception e) { + DefaultMessageStore.log.warn(this.getServiceName() + " service has exception. ", e); + } + } + DefaultMessageStore.log.info(this.getServiceName() + " service end"); + } - @Override - public long now() { - return this.systemClock.now(); - } + @Override + public String getServiceName() { + return ReputMessageService.class.getSimpleName(); + } - @Override - public HashMap getRuntimeInfo() { - // TODO Auto-generated method stub - return null; } @Override - public SelectMapedBufferResult selectOneMessageByOffset(long phyOffset) { - SelectMapedBufferResult sbr = this.commitLog.getMessage(phyOffset, 4); - if (null != sbr) { - try { - // 1 TOTALSIZE - int size = sbr.getByteBuffer().getInt(); - return this.commitLog.getMessage(phyOffset, size); - } - finally { - sbr.release(); + public long getCommitLogOffsetInQueue(String topic, int queueId, long cqOffset) { + ConsumeQueue consumeQueue = findConsumeQueue(topic, queueId); + if (consumeQueue != null) { + SelectMapedBufferResult bufferConsumeQueue = consumeQueue.getIndexBuffer(cqOffset); + if (bufferConsumeQueue != null) { + try { + long offsetPy = bufferConsumeQueue.getByteBuffer().getLong(); + return offsetPy; + } + finally { + bufferConsumeQueue.release(); + } } } - return null; - } - - - public ScheduleMessageService getScheduleMessageService() { - return scheduleMessageService; - } - - - public TransactionStateService getTransactionStateService() { - return transactionStateService; - } - - - public RunningFlags getRunningFlags() { - return runningFlags; + return 0; } - public TransactionCheckExecuter getTransactionCheckExecuter() { - return transactionCheckExecuter; + @Override + public long getMinPhyOffset() { + return this.commitLog.getMinOffset(); } } diff --git a/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/DispatchRequest.java b/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/DispatchRequest.java index 591a3017..6bebfc2b 100644 --- a/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/DispatchRequest.java +++ b/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/DispatchRequest.java @@ -1,12 +1,25 @@ /** - * $Id: DispatchRequest.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.store; /** - * ַϢλϢ߼к + * 分发消息位置信息到逻辑队列和索引服务 * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * @author shijia.wxr + * @since 2013-7-21 */ public class DispatchRequest { private final String topic; @@ -17,9 +30,8 @@ public class DispatchRequest { private final long storeTimestamp; private final long consumeQueueOffset; private final String keys; - /** - * ز + * 事务相关部分 */ private final int sysFlag; private final long tranStateTableOffset; @@ -37,12 +49,15 @@ public DispatchRequest(// final long consumeQueueOffset,// 7 final String keys,// 8 /** - * ز + * 事务相关部分 */ final int sysFlag,// 9 final long tranStateTableOffset,// 10 final long preparedTransactionOffset,// 11 final String producerGroup// 12 + // 如果producerGroup为空,表示是recover过程,所以不更新 + // Transaction state + // table ) { this.topic = topic; this.queueId = queueId; @@ -54,7 +69,7 @@ public DispatchRequest(// this.keys = keys; /** - * ز + * 事务相关部分 */ this.sysFlag = sysFlag; this.tranStateTableOffset = tranStateTableOffset; @@ -82,7 +97,7 @@ public DispatchRequest(int size) { this.keys = ""; /** - * ز + * 事务相关部分 */ this.sysFlag = 0; this.tranStateTableOffset = 0; diff --git a/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/GetMessageResult.java b/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/GetMessageResult.java index 4468e9c2..4563d971 100644 --- a/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/GetMessageResult.java +++ b/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/GetMessageResult.java @@ -1,5 +1,17 @@ /** - * $Id: GetMessageResult.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.store; @@ -9,26 +21,28 @@ /** - * Ϣؽ + * 访问消息返回结果 * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * @author shijia.wxr + * @since 2013-7-21 */ public class GetMessageResult { - // öٱȡϢ + // 多个连续的消息集合 + private final List messageMapedList = + new ArrayList(100); + // 用来向Consumer传送消息 + private final List messageBufferList = new ArrayList(100); + // 枚举变量,取消息结果 private GetMessageStatus status; - // ˺󣬷һοʼOffset + // 当被过滤后,返回下一次开始的Offset private long nextBeginOffset; - // ߼еСOffset + // 逻辑队列中的最小Offset private long minOffset; - // ߼еOffset + // 逻辑队列中的最大Offset private long maxOffset; - // Ϣ - private final List messageMapedList = new ArrayList(100); - // ConsumerϢ - private final List messageBufferList = new ArrayList(100); - // ByteBuffer ֽ + // ByteBuffer 总字节数 private int bufferTotalSize = 0; - // ǷslaveϢ + // 是否建议从slave拉消息 private boolean suggestPullingFromSlave = false; @@ -105,13 +119,13 @@ public int getBufferTotalSize() { } - public int getMessageCount() { - return this.messageMapedList.size(); + public void setBufferTotalSize(int bufferTotalSize) { + this.bufferTotalSize = bufferTotalSize; } - public void setBufferTotalSize(int bufferTotalSize) { - this.bufferTotalSize = bufferTotalSize; + public int getMessageCount() { + return this.messageMapedList.size(); } @@ -123,4 +137,13 @@ public boolean isSuggestPullingFromSlave() { public void setSuggestPullingFromSlave(boolean suggestPullingFromSlave) { this.suggestPullingFromSlave = suggestPullingFromSlave; } + + + @Override + public String toString() { + return "GetMessageResult [status=" + status + ", nextBeginOffset=" + nextBeginOffset + ", minOffset=" + + minOffset + ", maxOffset=" + maxOffset + ", bufferTotalSize=" + bufferTotalSize + + ", suggestPullingFromSlave=" + suggestPullingFromSlave + "]"; + } + } diff --git a/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/GetMessageStatus.java b/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/GetMessageStatus.java index d30f976f..7aa885de 100644 --- a/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/GetMessageStatus.java +++ b/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/GetMessageStatus.java @@ -1,30 +1,43 @@ /** - * $Id: GetMessageStatus.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.store; /** - * Ϣص״̬ + * 访问消息返回的状态码 * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * @author shijia.wxr + * @since 2013-7-21 */ public enum GetMessageStatus { - // ҵϢ + // 找到消息 FOUND, - // offsetȷǹ˺ûƥϢ + // offset正确,但是过滤后没有匹配的消息 NO_MATCHED_MESSAGE, - // offsetȷϢڱɾ + // offset正确,但是物理队列消息正在被删除 MESSAGE_WAS_REMOVING, - // offsetȷǴ߼ûҵڱɾ + // offset正确,但是从逻辑队列没有找到,可能正在被删除 OFFSET_FOUND_NULL, - // offset + // offset错误,严重溢出 OFFSET_OVERFLOW_BADLY, - // offset1 + // offset错误,溢出1个 OFFSET_OVERFLOW_ONE, - // offset̫С + // offset错误,太小了 OFFSET_TOO_SMALL, - // ûжӦ߼ + // 没有对应的逻辑队列 NO_MATCHED_LOGIC_QUEUE, - // һϢû + // 队列中一条消息都没有 NO_MESSAGE_IN_QUEUE, } diff --git a/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/MapedFile.java b/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/MapedFile.java index 35ece78b..398df93e 100644 --- a/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/MapedFile.java +++ b/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/MapedFile.java @@ -1,5 +1,17 @@ /** - * $Id: MapedFile.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.store; @@ -20,42 +32,41 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.alibaba.rocketmq.common.MixAll; -import com.alibaba.rocketmq.common.UtilALl; +import com.alibaba.rocketmq.common.UtilAll; +import com.alibaba.rocketmq.common.constant.LoggerName; /** - * Pagecacheļʷװ + * Pagecache文件访问封装 * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * @author shijia.wxr + * @since 2013-7-21 */ public class MapedFile extends ReferenceResource { - private static final Logger log = LoggerFactory.getLogger(MixAll.StoreLoggerName); public static final int OS_PAGE_SIZE = 1024 * 4; - // ǰJVMӳڴܴС + private static final Logger log = LoggerFactory.getLogger(LoggerName.StoreLoggerName); + // 当前JVM中映射的虚拟内存总大小 private static final AtomicLong TotalMapedVitualMemory = new AtomicLong(0); - // ǰJVMmmap + // 当前JVM中mmap句柄数量 private static final AtomicInteger TotalMapedFiles = new AtomicInteger(0); - - // ӳļ + // 映射的文件名 private final String fileName; - // ӳʼƫ + // 映射的起始偏移量 private final long fileFromOffset; - // ӳļС + // 映射的文件大小,定长 private final int fileSize; - // ӳļ + // 映射的文件 private final File file; - // ӳFileChannel - private final FileChannel fileChannel; - // ӳڴpositionԶ + // 映射的内存对象,position永远不变 private final MappedByteBuffer mappedByteBuffer; - // ǰдʲôλ + // 当前写到什么位置 private final AtomicInteger wrotePostion = new AtomicInteger(0); - // Flushʲôλ + // Flush到什么位置 private final AtomicInteger committedPosition = new AtomicInteger(0); - // һϢ洢ʱ + // 映射的FileChannel对象 + private FileChannel fileChannel; + // 最后一条消息存储时间 private volatile long storeTimestamp = 0; - private boolean firstCreateInQueue = false; @@ -102,6 +113,70 @@ public static void ensureDirOK(final String dirName) { } + public static void clean(final ByteBuffer buffer) { + if (buffer == null || !buffer.isDirect() || buffer.capacity() == 0) + return; + invoke(invoke(viewed(buffer), "cleaner"), "clean"); + } + + + private static Object invoke(final Object target, final String methodName, final Class... args) { + return AccessController.doPrivileged(new PrivilegedAction() { + public Object run() { + try { + Method method = method(target, methodName, args); + method.setAccessible(true); + return method.invoke(target); + } + catch (Exception e) { + throw new IllegalStateException(e); + } + } + }); + } + + + private static Method method(Object target, String methodName, Class[] args) + throws NoSuchMethodException { + try { + return target.getClass().getMethod(methodName, args); + } + catch (NoSuchMethodException e) { + return target.getClass().getDeclaredMethod(methodName, args); + } + } + + + private static ByteBuffer viewed(ByteBuffer buffer) { + String methodName = "viewedBuffer"; + + // JDK7中将DirectByteBuffer类中的viewedBuffer方法换成了attachment方法 + Method[] methods = buffer.getClass().getMethods(); + for (int i = 0; i < methods.length; i++) { + if (methods[i].getName().equals("attachment")) { + methodName = "attachment"; + break; + } + } + + ByteBuffer viewedBuffer = (ByteBuffer) invoke(buffer, methodName); + if (viewedBuffer == null) + return buffer; + else + return viewed(viewedBuffer); + } + + + public static int getTotalmapedfiles() { + return TotalMapedFiles.get(); + } + + + public static long getTotalMapedVitualMemory() { + return TotalMapedVitualMemory.get(); + } + + public long getLastModifiedTimestamp() { return this.file.lastModified(); } @@ -113,15 +188,7 @@ public String getFileName() { /** - * ļʼƫ - */ - public long getFileFromOffset() { - return this.fileFromOffset; - } - - - /** - * ȡļС + * 获取文件大小 */ public int getFileSize() { return fileSize; @@ -133,19 +200,14 @@ public FileChannel getFileChannel() { } - public boolean isFull() { - return this.fileSize == this.wrotePostion.get(); - } - - /** - * MapedBuffer׷Ϣ
+ * 向MapedBuffer追加消息
* * @param msg - * Ҫ׷ӵϢ + * 要追加的消息 * @param cb - * ϢлMapedFile OffsetԽж̬л - * @return Ƿɹд + * 用来对消息进行序列化,尤其对于依赖MapedFile Offset的属性进行动态序列化 + * @return 是否成功,写入多少数据 */ public AppendMessageResult appendMessage(final Object msg, final AppendMessageCallback cb) { assert msg != null; @@ -153,7 +215,7 @@ public AppendMessageResult appendMessage(final Object msg, final AppendMessageCa int currentPos = this.wrotePostion.get(); - // ʾпռ + // 表示有空余空间 if (currentPos < this.fileSize) { ByteBuffer byteBuffer = this.mappedByteBuffer.slice(); byteBuffer.position(currentPos); @@ -164,7 +226,7 @@ public AppendMessageResult appendMessage(final Object msg, final AppendMessageCa return result; } - // ϲӦӦñ֤ߵ + // 上层应用应该保证不会走到这里 log.error("MapedFile.appendMessage return null, wrotePostion: " + currentPos + " fileSize: " + this.fileSize); return new AppendMessageResult(AppendMessageStatus.UNKNOWN_ERROR); @@ -172,14 +234,22 @@ public AppendMessageResult appendMessage(final Object msg, final AppendMessageCa /** - * 洢׷ݣһSLAVE洢ṹʹ + * 文件起始偏移量 + */ + public long getFileFromOffset() { + return this.fileFromOffset; + } + + + /** + * 向存储层追加数据,一般在SLAVE存储结构中使用 * - * @return д˶ + * @return 返回写入了多少数据 */ public boolean appendMessage(final byte[] data) { int currentPos = this.wrotePostion.get(); - // ʾпռ + // 表示有空余空间 if ((currentPos + data.length) <= this.fileSize) { ByteBuffer byteBuffer = this.mappedByteBuffer.slice(); byteBuffer.position(currentPos); @@ -192,29 +262,11 @@ public boolean appendMessage(final byte[] data) { } - private boolean isAbleToFlush(final int flushLeastPages) { - int flush = this.committedPosition.get(); - int write = this.wrotePostion.get(); - - // ǰļѾдӦˢ - if (this.isFull()) { - return true; - } - - // ֻδˢָpageĿˢ - if (flushLeastPages > 0) { - return ((write / OS_PAGE_SIZE) - (flush / OS_PAGE_SIZE)) >= flushLeastPages; - } - - return write > flush; - } - - /** - * Ϣˢ + * 消息刷盘 * * @param flushLeastPages - * ˢpage + * 至少刷几个page * @return */ public int commit(final int flushLeastPages) { @@ -235,10 +287,43 @@ public int commit(final int flushLeastPages) { } + public int getCommittedPosition() { + return committedPosition.get(); + } + + + public void setCommittedPosition(int pos) { + this.committedPosition.set(pos); + } + + + private boolean isAbleToFlush(final int flushLeastPages) { + int flush = this.committedPosition.get(); + int write = this.wrotePostion.get(); + + // 如果当前文件已经写满,应该立刻刷盘 + if (this.isFull()) { + return true; + } + + // 只有未刷盘数据满足指定page数目才刷盘 + if (flushLeastPages > 0) { + return ((write / OS_PAGE_SIZE) - (flush / OS_PAGE_SIZE)) >= flushLeastPages; + } + + return write > flush; + } + + + public boolean isFull() { + return this.fileSize == this.wrotePostion.get(); + } + + public SelectMapedBufferResult selectMapedBuffer(int pos, int size) { - // Ϣ + // 有消息 if ((pos + size) <= this.wrotePostion.get()) { - // MapedBuffer + // 从MapedBuffer读 if (this.hold()) { ByteBuffer byteBuffer = this.mappedByteBuffer.slice(); byteBuffer.position(pos); @@ -251,19 +336,19 @@ public SelectMapedBufferResult selectMapedBuffer(int pos, int size) { + this.fileFromOffset); } } - // Ƿ + // 请求参数非法 else { log.warn("selectMapedBuffer request pos invalid, request pos: " + pos + ", size: " + size + ", fileFromOffset: " + this.fileFromOffset); } - // ǷmmapԴѾͷ + // 非法参数或者mmap资源已经被释放 return null; } /** - * ߼ + * 读逻辑分区 */ public SelectMapedBufferResult selectMapedBuffer(int pos) { if (pos < this.wrotePostion.get() && pos >= 0) { @@ -277,65 +362,25 @@ public SelectMapedBufferResult selectMapedBuffer(int pos) { } } - // ǷmmapԴѾͷ + // 非法参数或者mmap资源已经被释放 return null; } - public static void clean(final ByteBuffer buffer) { - if (buffer == null || !buffer.isDirect() || buffer.capacity() == 0) - return; - invoke(invoke(viewed(buffer), "cleaner"), "clean"); - } - - - private static Object invoke(final Object target, final String methodName, final Class... args) { - return AccessController.doPrivileged(new PrivilegedAction() { - public Object run() { - try { - Method method = method(target, methodName, args); - method.setAccessible(true); - return method.invoke(target); - } - catch (Exception e) { - throw new IllegalStateException(e); - } - } - }); - } - - - private static Method method(Object target, String methodName, Class[] args) throws NoSuchMethodException { - try { - return target.getClass().getMethod(methodName, args); - } - catch (NoSuchMethodException e) { - return target.getClass().getDeclaredMethod(methodName, args); - } - } - - - private static ByteBuffer viewed(ByteBuffer buffer) { - ByteBuffer viewedBuffer = (ByteBuffer) invoke(buffer, "viewedBuffer"); - if (viewedBuffer == null) - return buffer; - else - return viewed(viewedBuffer); - } - - @Override public boolean cleanup(final long currentRef) { - // ûбshutdown򲻿unmapļcrash + // 如果没有被shutdown,则不可以unmap文件,否则会crash if (this.isAvailable()) { - log.error("this file[REF:" + currentRef + "] " + this.fileName + " have not shutdown, stop unmaping."); + log.error("this file[REF:" + currentRef + "] " + this.fileName + + " have not shutdown, stop unmaping."); return false; } - // Ѿcleanupٴβcrash + // 如果已经cleanup,再次操作会引起crash if (this.isCleanupOver()) { - log.error("this file[REF:" + currentRef + "] " + this.fileName + " have cleanup, do not do it again."); - // 뷵true + log.error("this file[REF:" + currentRef + "] " + this.fileName + + " have cleanup, do not do it again."); + // 必须返回true return true; } @@ -348,9 +393,9 @@ public boolean cleanup(final long currentRef) { /** - * Դdestroyshutdowṉ߳ͬһ + * 清理资源,destroy与调用shutdown的线程必须是同一个 * - * @return ǷdestoryɹϲҪʧʧܺ + * @return 是否被destory成功,上层调用需要对失败情况处理,失败后尝试重试 */ public boolean destroy(final long intervalForcibly) { this.shutdown(intervalForcibly); @@ -364,7 +409,8 @@ public boolean destroy(final long intervalForcibly) { boolean result = this.file.delete(); log.info("delete file[REF:" + this.getRefCount() + "] " + this.fileName + (result ? " OK, " : " Failed, ") + "W:" + this.getWrotePostion() + " M:" - + this.getCommittedPosition() + ", " + UtilALl.computeEclipseTimeMilliseconds(beginTime)); + + this.getCommittedPosition() + ", " + + UtilAll.computeEclipseTimeMilliseconds(beginTime)); } catch (Exception e) { log.warn("close file channel " + this.fileName + " Failed. ", e); @@ -386,38 +432,18 @@ public int getWrotePostion() { } - public int getCommittedPosition() { - return committedPosition.get(); - } - - public void setWrotePostion(int pos) { this.wrotePostion.set(pos); } - public void setCommittedPosition(int pos) { - this.committedPosition.set(pos); - } - - - public static int getTotalmapedfiles() { - return TotalMapedFiles.get(); - } - - - public static long getTotalMapedVitualMemory() { - return TotalMapedVitualMemory.get(); - } - - public MappedByteBuffer getMappedByteBuffer() { return mappedByteBuffer; } /** - * ʱãȫֻʱreloadʱ + * 方法不能在运行时调用,不安全。只在启动时,reload已有数据时调用 */ public ByteBuffer sliceByteBuffer() { return this.mappedByteBuffer.slice(); diff --git a/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/MapedFileQueue.java b/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/MapedFileQueue.java index a3219514..ce7c9a14 100644 --- a/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/MapedFileQueue.java +++ b/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/MapedFileQueue.java @@ -1,5 +1,17 @@ /** - * $Id: MapedFileQueue.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.store; @@ -14,33 +26,34 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.alibaba.rocketmq.common.MixAll; -import com.alibaba.rocketmq.common.UtilALl; +import com.alibaba.rocketmq.common.UtilAll; +import com.alibaba.rocketmq.common.constant.LoggerName; /** - * 洢Уݶʱɾ
- * ɶļ - * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * 存储队列,数据定时删除,无限增长
+ * 队列是由多个文件组成 + * + * @author shijia.wxr + * @since 2013-7-21 */ public class MapedFileQueue { - private static final Logger log = LoggerFactory.getLogger(MixAll.StoreLoggerName); - // ÿδɾļɾٸļ + private static final Logger log = LoggerFactory.getLogger(LoggerName.StoreLoggerName); + // 每次触发删除文件,最多删除多少个文件 private static final int DeleteFilesBatchMax = 30; - // ļ洢λ + // 文件存储位置 private final String storePath; - // ÿļĴС + // 每个文件的大小 private final int mapedFileSize; - // ˢˢ - private long committedWhere = 0; - // ļ + // 各个文件 private final List mapedFiles = new ArrayList(); - // дmapedFiles + // 读写锁(针对mapedFiles) private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock(); - // ԤMapedFile + // 预分配MapedFile对象服务 private final AllocateMapedFileService allocateMapedFileService; - // һϢ洢ʱ + // 刷盘刷到哪里 + private long committedWhere = 0; + // 最后一条消息存储时间 private volatile long storeTimestamp = 0; @@ -69,8 +82,29 @@ public MapedFile getMapedFileByTime(final long timestamp) { } + private Object[] copyMapedFiles(final int reservedMapedFiles) { + Object[] mfs = null; + + try { + this.readWriteLock.readLock().lock(); + if (this.mapedFiles.size() <= reservedMapedFiles) { + return null; + } + + mfs = this.mapedFiles.toArray(); + } + catch (Exception e) { + e.printStackTrace(); + } + finally { + this.readWriteLock.readLock().unlock(); + } + return mfs; + } + + /** - * recoverʱãҪ + * recover时调用,不需要加锁 */ public void truncateDirtyFiles(long offset) { List willRemoveFiles = new ArrayList(); @@ -83,7 +117,7 @@ public void truncateDirtyFiles(long offset) { file.setCommittedPosition((int) (offset % this.mapedFileSize)); } else { - // ļɾ + // 将文件删除掉 file.destroy(1000); willRemoveFiles.add(file); } @@ -94,6 +128,30 @@ public void truncateDirtyFiles(long offset) { } + /** + * 删除文件只能从头开始删 + */ + private void deleteExpiredFile(List files) { + if (!files.isEmpty()) { + try { + this.readWriteLock.writeLock().lock(); + for (MapedFile file : files) { + if (!this.mapedFiles.remove(file)) { + log.error("deleteExpiredFile remove failed."); + break; + } + } + } + catch (Exception e) { + log.error("deleteExpiredFile has exception.", e); + } + finally { + this.readWriteLock.writeLock().unlock(); + } + } + } + + public boolean load() { File dir = new File(this.storePath); File[] files = dir.listFiles(); @@ -101,14 +159,14 @@ public boolean load() { // ascending order Arrays.sort(files); for (File file : files) { - // УļСǷƥ + // 校验文件大小是否匹配 if (file.length() != this.mapedFileSize) { log.warn(file + "\t" + file.length() + " length not matched message store config value, ignore it"); return true; } - // ָ + // 恢复队列 try { MapedFile mapedFile = new MapedFile(file.getPath(), mapedFileSize); @@ -129,7 +187,7 @@ public boolean load() { /** - * ˢ̽˶ + * 刷盘进度落后了多少 */ public long howMuchFallBehind() { if (this.mapedFiles.isEmpty()) @@ -147,8 +205,75 @@ public long howMuchFallBehind() { } + public MapedFile getLastMapedFile() { + return this.getLastMapedFile(0); + } + + /** - * ȡеСOffsetΪգ򷵻-1 + * 获取最后一个MapedFile对象,如果一个都没有,则新创建一个,如果最后一个写满了,则新创建一个 + * + * @param startOffset + * 如果创建新的文件,起始offset + * @return + */ + public MapedFile getLastMapedFile(final long startOffset) { + long createOffset = -1; + MapedFile mapedFileLast = null; + { + this.readWriteLock.readLock().lock(); + if (this.mapedFiles.isEmpty()) { + createOffset = startOffset - (startOffset % this.mapedFileSize); + } + else { + mapedFileLast = this.mapedFiles.get(this.mapedFiles.size() - 1); + } + this.readWriteLock.readLock().unlock(); + } + + if (mapedFileLast != null && mapedFileLast.isFull()) { + createOffset = mapedFileLast.getFileFromOffset() + this.mapedFileSize; + } + + if (createOffset != -1) { + String nextFilePath = this.storePath + File.separator + UtilAll.offset2FileName(createOffset); + String nextNextFilePath = + this.storePath + File.separator + + UtilAll.offset2FileName(createOffset + this.mapedFileSize); + MapedFile mapedFile = null; + + if (this.allocateMapedFileService != null) { + mapedFile = + this.allocateMapedFileService.putRequestAndReturnMapedFile(nextFilePath, + nextNextFilePath, this.mapedFileSize); + } + else { + try { + mapedFile = new MapedFile(nextFilePath, this.mapedFileSize); + } + catch (IOException e) { + log.error("create mapedfile exception", e); + } + } + + if (mapedFile != null) { + this.readWriteLock.writeLock().lock(); + if (this.mapedFiles.isEmpty()) { + mapedFile.setFirstCreateInQueue(true); + } + this.mapedFiles.add(mapedFile); + this.readWriteLock.writeLock().unlock(); + } + + return mapedFile; + } + + return mapedFileLast; + } + + + /** + * 获取队列的最小Offset,如果队列为空,则返回-1 */ public long getMinOffset() { try { @@ -189,7 +314,7 @@ public long getMaxOffset() { /** - * ָʱ + * 恢复时调用 */ public void deleteLastMapedFile() { if (!this.mapedFiles.isEmpty()) { @@ -203,40 +328,20 @@ public void deleteLastMapedFile() { /** - * ɾļֻܴͷʼɾ - */ - private void deleteExpiredFile(List files) { - if (!files.isEmpty()) { - try { - this.readWriteLock.writeLock().lock(); - for (MapedFile file : files) { - if (!this.mapedFiles.remove(file)) { - log.error("deleteExpiredFile remove failed."); - break; - } - } - } - catch (Exception e) { - log.error("deleteExpiredFile has exception.", e); - } - finally { - this.readWriteLock.writeLock().unlock(); - } - } - } - - - /** - * ļʱɾļ + * 根据文件过期时间来删除物理队列文件 */ - public int deleteExpiredFileByTime(final long expiredTime, final int deleteFilesInterval, - final long intervalForcibly) { + public int deleteExpiredFileByTime(// + final long expiredTime, // + final int deleteFilesInterval, // + final long intervalForcibly,// + final boolean cleanImmediately// + ) { Object[] mfs = this.copyMapedFiles(0); if (null == mfs) return 0; - // һļд״̬ɾ + // 最后一个文件处于写状态,不能删除 int mfsLength = mfs.length - 1; int deleteCount = 0; List files = new ArrayList(); @@ -244,7 +349,8 @@ public int deleteExpiredFileByTime(final long expiredTime, final int deleteFiles for (int i = 0; i < mfsLength; i++) { MapedFile mapedFile = (MapedFile) mfs[i]; long liveMaxTimestamp = mapedFile.getLastModifiedTimestamp() + expiredTime; - if (System.currentTimeMillis() >= liveMaxTimestamp) { + if (System.currentTimeMillis() >= liveMaxTimestamp// + || cleanImmediately) { if (mapedFile.destroy(intervalForcibly)) { files.add(mapedFile); deleteCount++; @@ -276,10 +382,10 @@ public int deleteExpiredFileByTime(final long expiredTime, final int deleteFiles /** - * СOffsetɾ߼ - * + * 根据物理队列最小Offset来删除逻辑队列 + * * @param offset - * Сoffset + * 物理队列最小offset */ public int deleteExpiredFileByOffset(long offset, int unitSize) { Object[] mfs = this.copyMapedFiles(0); @@ -287,10 +393,10 @@ public int deleteExpiredFileByOffset(long offset, int unitSize) { List files = new ArrayList(); int deleteCount = 0; if (null != mfs) { - // һļд״̬ɾ + // 最后一个文件处于写状态,不能删除 int mfsLength = mfs.length - 1; - // Χ 0 ... last - 1 + // 这里遍历范围 0 ... last - 1 for (int i = 0; i < mfsLength; i++) { boolean destroy = true; MapedFile mapedFile = (MapedFile) mfs[i]; @@ -298,7 +404,7 @@ public int deleteExpiredFileByOffset(long offset, int unitSize) { if (result != null) { long maxOffsetInLogicQueue = result.getByteBuffer().getLong(); result.release(); - // ǰļǷɾ + // 当前文件是否可以删除 destroy = (maxOffsetInLogicQueue < offset); if (destroy) { log.info("physic min offset " + offset + ", logics in current mapedfile max offset " @@ -327,8 +433,8 @@ public int deleteExpiredFileByOffset(long offset, int unitSize) { /** - * ֵʾǷȫˢ - * + * 返回值表示是否全部刷盘完成 + * * @return */ public boolean commit(final int flushLeastPages) { @@ -349,92 +455,6 @@ public boolean commit(final int flushLeastPages) { } - public MapedFile getLastMapedFile2() { - if (this.mapedFiles.isEmpty()) { - return null; - } - return this.mapedFiles.get(this.mapedFiles.size() - 1); - } - - - public MapedFile getLastMapedFile() { - return this.getLastMapedFile(0); - } - - - /** - * ȡһMapedFileһûУ´һһдˣ´һ - * - * @param startOffset - * µļʼoffset - * @return - */ - public MapedFile getLastMapedFile(final long startOffset) { - long createOffset = -1; - MapedFile mapedFileLast = null; - { - this.readWriteLock.readLock().lock(); - if (this.mapedFiles.isEmpty()) { - createOffset = startOffset - (startOffset % this.mapedFileSize); - } - else { - mapedFileLast = this.mapedFiles.get(this.mapedFiles.size() - 1); - } - this.readWriteLock.readLock().unlock(); - } - - if (mapedFileLast != null && mapedFileLast.isFull()) { - createOffset = mapedFileLast.getFileFromOffset() + this.mapedFileSize; - } - - if (createOffset != -1) { - String nextFilePath = this.storePath + File.separator + UtilALl.offset2FileName(createOffset); - String nextNextFilePath = - this.storePath + File.separator + UtilALl.offset2FileName(createOffset + this.mapedFileSize); - MapedFile mapedFile = - this.allocateMapedFileService.putRequestAndReturnMapedFile(nextFilePath, nextNextFilePath, - this.mapedFileSize); - if (mapedFile != null) { - this.readWriteLock.writeLock().lock(); - if (this.mapedFiles.isEmpty()) { - mapedFile.setFirstCreateInQueue(true); - } - this.mapedFiles.add(mapedFile); - this.readWriteLock.writeLock().unlock(); - } - - return mapedFile; - } - - return mapedFileLast; - } - - - private MapedFile getFirstMapedFile() { - if (this.mapedFiles.isEmpty()) { - return null; - } - - return this.mapedFiles.get(0); - } - - - public MapedFile getFirstMapedFileOnLock() { - try { - this.readWriteLock.readLock().lock(); - return this.getFirstMapedFile(); - } - finally { - this.readWriteLock.readLock().unlock(); - } - } - - - public MapedFile findMapedFileByOffset(final long offset) { - return findMapedFileByOffset(offset, false); - } - - public MapedFile findMapedFileByOffset(final long offset, final boolean returnFirstOnNotFound) { try { this.readWriteLock.readLock().lock(); @@ -444,9 +464,9 @@ public MapedFile findMapedFileByOffset(final long offset, final boolean returnFi int index = (int) ((offset / this.mapedFileSize) - (mapedFile.getFileFromOffset() / this.mapedFileSize)); if (index < 0 || index >= this.mapedFiles.size()) { - log.warn("findMapedFileByOffset offset not matched, request Offset: " + offset + ", index: " - + index + ", mapedFileSize: " + this.mapedFileSize + ", mapedFiles count: " - + this.mapedFiles.size()); + log.warn("findMapedFileByOffset offset not matched, request Offset: " + offset + + ", index: " + index + ", mapedFileSize: " + this.mapedFileSize + + ", mapedFiles count: " + this.mapedFiles.size()); } try { @@ -470,6 +490,28 @@ public MapedFile findMapedFileByOffset(final long offset, final boolean returnFi } + private MapedFile getFirstMapedFile() { + if (this.mapedFiles.isEmpty()) { + return null; + } + + return this.mapedFiles.get(0); + } + + + public MapedFile getLastMapedFile2() { + if (this.mapedFiles.isEmpty()) { + return null; + } + return this.mapedFiles.get(this.mapedFiles.size() - 1); + } + + + public MapedFile findMapedFileByOffset(final long offset) { + return findMapedFileByOffset(offset, false); + } + + public long getMapedMemorySize() { long size = 0; @@ -486,27 +528,6 @@ public long getMapedMemorySize() { } - private Object[] copyMapedFiles(final int reservedMapedFiles) { - Object[] mfs = null; - - try { - this.readWriteLock.readLock().lock(); - if (this.mapedFiles.size() <= reservedMapedFiles) { - return null; - } - - mfs = this.mapedFiles.toArray(); - } - catch (Exception e) { - e.printStackTrace(); - } - finally { - this.readWriteLock.readLock().unlock(); - } - return mfs; - } - - public boolean retryDeleteFirstFile(final long intervalForcibly) { MapedFile mapedFile = this.getFirstMapedFileOnLock(); if (mapedFile != null) { @@ -531,8 +552,19 @@ public boolean retryDeleteFirstFile(final long intervalForcibly) { } + public MapedFile getFirstMapedFileOnLock() { + try { + this.readWriteLock.readLock().lock(); + return this.getFirstMapedFile(); + } + finally { + this.readWriteLock.readLock().unlock(); + } + } + + /** - * رնУݻڣDzܷ + * 关闭队列,队列数据还在,但是不能访问 */ public void shutdown(final long intervalForcibly) { this.readWriteLock.readLock().lock(); @@ -544,7 +576,7 @@ public void shutdown(final long intervalForcibly) { /** - * ٶУݱɾ˺пܲɹ + * 销毁队列,队列数据被删除,此函数有可能不成功 */ public void destroy() { this.readWriteLock.writeLock().lock(); diff --git a/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/MessageExtBrokerInner.java b/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/MessageExtBrokerInner.java index a4d29df2..2e454d66 100644 --- a/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/MessageExtBrokerInner.java +++ b/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/MessageExtBrokerInner.java @@ -1,21 +1,47 @@ /** - * $Id: MessageExtBrokerInner.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.store; -import com.alibaba.rocketmq.common.MessageExt; import com.alibaba.rocketmq.common.TopicFilterType; +import com.alibaba.rocketmq.common.message.MessageExt; /** - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * 存储内部使用的Message对象 * + * @author shijia.wxr + * @since 2013-7-21 */ public class MessageExtBrokerInner extends MessageExt { + private static final long serialVersionUID = 7256001576878700634L; private String propertiesString; private long tagsCode; + /** + * 目前只支持单个标签的过滤 + */ + public static long tagsString2tagsCode(final TopicFilterType filter, final String tags) { + if (null == tags || tags.length() == 0) + return 0; + + return tags.hashCode(); + } + + public String getPropertiesString() { return propertiesString; } @@ -34,12 +60,4 @@ public long getTagsCode() { public void setTagsCode(long tagsCode) { this.tagsCode = tagsCode; } - - - public static long tagsString2tagsCode(final TopicFilterType filter, final String tags) { - if (null == tags || tags.length() == 0) - return 0; - // TODO - return 0; - } } diff --git a/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/MessageFilter.java b/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/MessageFilter.java index f5b5f025..e76fac25 100644 --- a/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/MessageFilter.java +++ b/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/MessageFilter.java @@ -1,5 +1,17 @@ /** - * $Id: MessageFilter.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.store; @@ -7,9 +19,10 @@ /** - * Ϣ˽ӿ + * 消息过滤接口 * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * @author shijia.wxr + * @since 2013-7-21 */ public interface MessageFilter { public boolean isMessageMatched(final SubscriptionData subscriptionData, final long tagsCode); diff --git a/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/MessageStore.java b/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/MessageStore.java index 6b04e925..e76041a1 100644 --- a/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/MessageStore.java +++ b/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/MessageStore.java @@ -1,145 +1,173 @@ /** - * $Id: MessageStore.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.store; import java.util.HashMap; -import com.alibaba.rocketmq.common.MessageExt; +import com.alibaba.rocketmq.common.message.MessageExt; import com.alibaba.rocketmq.common.protocol.heartbeat.SubscriptionData; /** - * 洢ṩĽӿ + * 存储层对外提供的接口 * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * @author shijia.wxr + * @since 2013-7-21 */ public interface MessageStore { /** - * ʱ + * 重启时,加载数据 */ public boolean load(); /** - * + * 启动服务 */ public void start() throws Exception; /** - * رշ + * 关闭服务 */ public void shutdown(); /** - * ɾļԪԻʹ + * 删除所有文件,单元测试会使用 */ public void destroy(); /** - * 洢Ϣ + * 存储消息 */ public PutMessageResult putMessage(final MessageExtBrokerInner msg); /** - * ȡϢtypesΪnull + * 读取消息,如果types为null,则不做过滤 */ public GetMessageResult getMessage(final String topic, final int queueId, final long offset, final int maxMsgNums, final SubscriptionData subscriptionData); /** - * ȡָOffset вڣ-1 + * 获取指定队列最大Offset 如果队列不存在,返回-1 */ public long getMaxOffsetInQuque(final String topic, final int queueId); /** - * ȡָСOffset вڣ-1 + * 获取指定队列最小Offset 如果队列不存在,返回-1 */ public long getMinOffsetInQuque(final String topic, final int queueId); /** - * ϢʱȡijжӦoffset 1ָʱ䣨֮ǰ֮жӦϢȡʱoffsetѡ֮ǰ - * 2ָʱ޶ӦϢ򷵻0 + * 获取消费队列记录的CommitLog Offset + */ + public long getCommitLogOffsetInQueue(final String topic, final int queueId, final long cqOffset); + + + /** + * 根据消息时间获取某个队列中对应的offset 1、如果指定时间(包含之前之后)有对应的消息,则获取距离此时间最近的offset(优先选择之前) + * 2、如果指定时间无对应消息,则返回0 */ public long getOffsetInQueueByTime(final String topic, final int queueId, final long timestamp); /** - * ͨOffsetѯϢ 򷵻null + * 通过物理队列Offset,查询消息。 如果发生错误,则返回null */ - public MessageExt lookMessageByOffset(final long phyOffset); + public MessageExt lookMessageByOffset(final long commitLogOffset); /** - * ͨOffsetѯϢ 򷵻null + * 通过物理队列Offset,查询消息。 如果发生错误,则返回null */ - public SelectMapedBufferResult selectOneMessageByOffset(final long phyOffset); + public SelectMapedBufferResult selectOneMessageByOffset(final long commitLogOffset); + + + public SelectMapedBufferResult selectOneMessageByOffset(final long commitLogOffset, final int msgSize); /** - * ȡʱͳ + * 获取运行时统计数据 */ public String getRunningDataInfo(); /** - * ȡʱͳ + * 获取运行时统计数据 */ public HashMap getRuntimeInfo(); /** - * ȡoffset + * 获取物理队列最大offset */ public long getMaxPhyOffset(); + public long getMinPhyOffset(); + + /** - * ȡϢʱ + * 获取队列中最早的消息时间 */ public long getEarliestMessageTime(final String topic, final int queueId); + public long getMessageStoreTimeStamp(final String topic, final int queueId, final long offset); + + /** - * ȡеϢ + * 获取队列中的消息总数 */ public long getMessageTotalInQueue(final String topic, final int queueId); /** - * ݸʹãȡCommitLog + * 数据复制使用:获取CommitLog数据 */ public SelectMapedBufferResult getCommitLogData(final long offset); /** - * ݸʹãCommitLog׷ݣַConsume Queue + * 数据复制使用:向CommitLog追加数据,并分发至各个Consume Queue */ public boolean appendToCommitLog(final long startOffset, final byte[] data); /** - * ֶɾļ + * 手动触发删除文件 */ public void excuteDeleteFilesManualy(); /** - * ϢKeyѯϢ + * 根据消息Key查询消息 */ public QueryMessageResult queryMessage(final String topic, final String key, final int maxNum, final long begin, final long end); - public void updateMasterAddress(final String newAddr); + public void updateHaMasterAddress(final String newAddr); public long now(); diff --git a/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/PutMessageResult.java b/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/PutMessageResult.java index 772e2cad..89051cf5 100644 --- a/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/PutMessageResult.java +++ b/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/PutMessageResult.java @@ -1,12 +1,25 @@ /** - * $Id: PutMessageResult.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.store; /** - * дϢؽ + * 写入消息返回结果 * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * @author shijia.wxr + * @since 2013-7-21 */ public class PutMessageResult { private PutMessageStatus putMessageStatus; @@ -20,7 +33,7 @@ public PutMessageResult(PutMessageStatus putMessageStatus, AppendMessageResult a public boolean isOk() { - return this.appendMessageResult.isOk(); + return this.appendMessageResult != null && this.appendMessageResult.isOk(); } @@ -42,4 +55,12 @@ public PutMessageStatus getPutMessageStatus() { public void setPutMessageStatus(PutMessageStatus putMessageStatus) { this.putMessageStatus = putMessageStatus; } + + + @Override + public String toString() { + return "PutMessageResult [putMessageStatus=" + putMessageStatus + ", appendMessageResult=" + + appendMessageResult + "]"; + } + } diff --git a/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/PutMessageStatus.java b/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/PutMessageStatus.java index d6a03b8e..5a307bfb 100644 --- a/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/PutMessageStatus.java +++ b/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/PutMessageStatus.java @@ -1,11 +1,25 @@ /** - * $Id: PutMessageStatus.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.store; /** - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * 写入消息过程的返回结果 * + * @author shijia.wxr + * @since 2013-7-21 */ public enum PutMessageStatus { PUT_OK, diff --git a/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/QueryMessageResult.java b/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/QueryMessageResult.java index e0fca5d3..9f91fc66 100644 --- a/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/QueryMessageResult.java +++ b/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/QueryMessageResult.java @@ -1,5 +1,17 @@ /** - * $Id: QueryMessageResult.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.store; @@ -9,17 +21,20 @@ /** + * 通过Key查询消息,返回结果 * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * @author shijia.wxr + * @since 2013-7-21 */ public class QueryMessageResult { + // 多个连续的消息集合 + private final List messageMapedList = + new ArrayList(100); + // 用来向Consumer传送消息 + private final List messageBufferList = new ArrayList(100); private long indexLastUpdateTimestamp; private long indexLastUpdatePhyoffset; - // Ϣ - private final List messageMapedList = new ArrayList(100); - // ConsumerϢ - private final List messageBufferList = new ArrayList(100); - // ByteBuffer ֽ + // ByteBuffer 总字节数 private int bufferTotalSize = 0; diff --git a/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/ReferenceResource.java b/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/ReferenceResource.java index 8beb3e08..a6c97a8b 100644 --- a/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/ReferenceResource.java +++ b/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/ReferenceResource.java @@ -1,5 +1,17 @@ /** - * $Id: ReferenceResource.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.store; @@ -7,9 +19,10 @@ /** - * ü࣬C++ָʵ + * 引用计数基类,类似于C++智能指针实现 * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * @author shijia.wxr + * @since 2013-7-21 */ public abstract class ReferenceResource { protected final AtomicLong refCount = new AtomicLong(1); @@ -19,7 +32,7 @@ public abstract class ReferenceResource { /** - * ԴǷHOLDס + * 资源是否能HOLD住 */ public synchronized boolean hold() { if (this.isAvailable()) { @@ -36,22 +49,15 @@ public synchronized boolean hold() { /** - * ͷԴ + * 资源是否可用,即是否可被HOLD */ - public void release() { - long value = this.refCount.decrementAndGet(); - if (value > 0) - return; - - synchronized (this) { - // cleanupڲҪǷclean - this.cleanupOver = this.cleanup(value); - } + public boolean isAvailable() { + return this.available; } /** - * ֹԴ shutdownöΣɹ̵߳ + * 禁止资源被访问 shutdown不允许调用多次,最好是由管理线程调用 */ public void shutdown(final long intervalForcibly) { if (this.available) { @@ -59,7 +65,7 @@ public void shutdown(final long intervalForcibly) { this.firstShutdownTimestamp = System.currentTimeMillis(); this.release(); } - // ǿshutdown + // 强制shutdown else if (this.getRefCount() > 0) { if ((System.currentTimeMillis() - this.firstShutdownTimestamp) >= intervalForcibly) { this.refCount.set(-1000 - this.getRefCount()); @@ -69,26 +75,33 @@ else if (this.getRefCount() > 0) { } - /** - * ԴǷãǷɱHOLD - */ - public boolean isAvailable() { - return this.available; + public long getRefCount() { + return this.refCount.get(); } /** - * ԴǷ + * 释放资源 */ - public boolean isCleanupOver() { - return this.refCount.get() <= 0 && this.cleanupOver; - } - + public void release() { + long value = this.refCount.decrementAndGet(); + if (value > 0) + return; - public long getRefCount() { - return this.refCount.get(); + synchronized (this) { + // cleanup内部要对是否clean做处理 + this.cleanupOver = this.cleanup(value); + } } public abstract boolean cleanup(final long currentRef); + + + /** + * 资源是否被清理完成 + */ + public boolean isCleanupOver() { + return this.refCount.get() <= 0 && this.cleanupOver; + } } diff --git a/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/RunningFlags.java b/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/RunningFlags.java index a2eac59c..89727f65 100644 --- a/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/RunningFlags.java +++ b/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/RunningFlags.java @@ -1,48 +1,60 @@ /** - * $Id: RunningFlags.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.store; /** - * 洢ģй̵״̬λ + * 存储模型运行过程的状态位 * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * @author shijia.wxr + * @since 2013-7-21 */ public class RunningFlags { - // ֹȨ + // 禁止读权限 private static final int NotReadableBit = 1; - // ֹдȨ + // 禁止写权限 private static final int NotWriteableBit = 1 << 1; - // ߼Ƿ + // 逻辑队列是否发生错误 private static final int WriteLogicsQueueErrorBit = 1 << 2; - // ļǷ + // 索引文件是否发生错误 private static final int WriteIndexFileErrorBit = 1 << 3; - // ̿ռ䲻 + // 磁盘空间不足 private static final int DiskFullBit = 1 << 4; - private volatile int flagBits = 0; - public int getFlagBits() { - return flagBits; + public RunningFlags() { } - public RunningFlags() { + public int getFlagBits() { + return flagBits; } - public boolean isReadable() { - if ((this.flagBits & NotReadableBit) == 0) { - return true; + public boolean getAndMakeReadable() { + boolean result = this.isReadable(); + if (!result) { + this.flagBits &= ~NotReadableBit; } - - return false; + return result; } - public boolean isWriteable() { - if ((this.flagBits & (NotWriteableBit | WriteLogicsQueueErrorBit | DiskFullBit | WriteIndexFileErrorBit)) == 0) { + public boolean isReadable() { + if ((this.flagBits & NotReadableBit) == 0) { return true; } @@ -50,15 +62,6 @@ public boolean isWriteable() { } - public boolean getAndMakeReadable() { - boolean result = this.isReadable(); - if (!result) { - this.flagBits &= ~NotReadableBit; - } - return result; - } - - public boolean getAndMakeNotReadable() { boolean result = this.isReadable(); if (result) { @@ -77,6 +80,15 @@ public boolean getAndMakeWriteable() { } + public boolean isWriteable() { + if ((this.flagBits & (NotWriteableBit | WriteLogicsQueueErrorBit | DiskFullBit | WriteIndexFileErrorBit)) == 0) { + return true; + } + + return false; + } + + public boolean getAndMakeNotWriteable() { boolean result = this.isWriteable(); if (result) { @@ -115,7 +127,7 @@ public boolean isIndexFileError() { /** - * DiskǷ + * 返回Disk是否正常 */ public boolean getAndMakeDiskFull() { boolean result = !((this.flagBits & DiskFullBit) == DiskFullBit); @@ -125,7 +137,7 @@ public boolean getAndMakeDiskFull() { /** - * DiskǷ + * 返回Disk是否正常 */ public boolean getAndMakeDiskOK() { boolean result = !((this.flagBits & DiskFullBit) == DiskFullBit); diff --git a/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/SelectMapedBufferResult.java b/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/SelectMapedBufferResult.java index 8343686d..4c71a371 100644 --- a/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/SelectMapedBufferResult.java +++ b/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/SelectMapedBufferResult.java @@ -1,5 +1,17 @@ /** - * $Id: SelectMapedBufferResult.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.store; @@ -7,18 +19,19 @@ /** - * ѯPagecacheؽ + * 查询Pagecache返回结果 * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * @author shijia.wxr + * @since 2013-7-21 */ public class SelectMapedBufferResult { - // ӶĸOffsetʼ + // 从队列中哪个绝对Offset开始 private final long startOffset; - // position0ʼ + // position从0开始 private final ByteBuffer byteBuffer; - // ЧݴС + // 有效数据大小 private int size; - // ͷڴ + // 用来释放内存 private MapedFile mapedFile; @@ -30,12 +43,6 @@ public SelectMapedBufferResult(long startOffset, ByteBuffer byteBuffer, int size } - public void setSize(final int s) { - this.size = s; - this.byteBuffer.limit(this.size); - } - - public ByteBuffer getByteBuffer() { return byteBuffer; } @@ -46,26 +53,32 @@ public int getSize() { } + public void setSize(final int s) { + this.size = s; + this.byteBuffer.limit(this.size); + } + + public MapedFile getMapedFile() { return mapedFile; } - /** - * ˷ֻܱһΣظЧ - */ - public synchronized void release() { + @Override + protected void finalize() { if (this.mapedFile != null) { - this.mapedFile.release(); - this.mapedFile = null; + this.release(); } } - @Override - protected void finalize() { + /** + * 此方法只能被调用一次,重复调用无效 + */ + public synchronized void release() { if (this.mapedFile != null) { - this.release(); + this.mapedFile.release(); + this.mapedFile = null; } } diff --git a/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/StoreCheckpoint.java b/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/StoreCheckpoint.java index 54590acc..98b91bdd 100644 --- a/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/StoreCheckpoint.java +++ b/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/StoreCheckpoint.java @@ -1,5 +1,17 @@ /** - * $Id: StoreCheckpoint.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.store; @@ -13,24 +25,24 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.alibaba.rocketmq.common.MixAll; -import com.alibaba.rocketmq.common.UtilALl; +import com.alibaba.rocketmq.common.UtilAll; +import com.alibaba.rocketmq.common.constant.LoggerName; /** - * ¼洢ģһµʱ + * 记录存储模型最终一致的时间点 * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * @author shijia.wxr + * @since 2013-7-21 */ public class StoreCheckpoint { - private static final Logger log = LoggerFactory.getLogger(MixAll.StoreLoggerName); - private volatile long physicMsgTimestamp = 0; - private volatile long logicsMsgTimestamp = 0; - private volatile long indexMsgTimestamp = 0; - + private static final Logger log = LoggerFactory.getLogger(LoggerName.StoreLoggerName); private final RandomAccessFile randomAccessFile; private final FileChannel fileChannel; private final MappedByteBuffer mappedByteBuffer; + private volatile long physicMsgTimestamp = 0; + private volatile long logicsMsgTimestamp = 0; + private volatile long indexMsgTimestamp = 0; public StoreCheckpoint(final String scpPath) throws IOException { @@ -46,11 +58,14 @@ public StoreCheckpoint(final String scpPath) throws IOException { log.info("store checkpoint file exists, " + scpPath); this.physicMsgTimestamp = this.mappedByteBuffer.getLong(0); this.logicsMsgTimestamp = this.mappedByteBuffer.getLong(8); + this.indexMsgTimestamp = this.mappedByteBuffer.getLong(16); log.info("store checkpoint file physicMsgTimestamp " + this.physicMsgTimestamp + ", " - + UtilALl.timeMillisToHumanString(this.physicMsgTimestamp)); + + UtilAll.timeMillisToHumanString(this.physicMsgTimestamp)); log.info("store checkpoint file logicsMsgTimestamp " + this.logicsMsgTimestamp + ", " - + UtilALl.timeMillisToHumanString(this.logicsMsgTimestamp)); + + UtilAll.timeMillisToHumanString(this.logicsMsgTimestamp)); + log.info("store checkpoint file indexMsgTimestamp " + this.indexMsgTimestamp + ", " + + UtilAll.timeMillisToHumanString(this.indexMsgTimestamp)); } else { log.info("store checkpoint file not exists, " + scpPath); @@ -58,14 +73,6 @@ public StoreCheckpoint(final String scpPath) throws IOException { } - public void flush() { - this.mappedByteBuffer.putLong(0, this.physicMsgTimestamp); - this.mappedByteBuffer.putLong(8, this.logicsMsgTimestamp); - this.mappedByteBuffer.putLong(16, this.indexMsgTimestamp); - this.mappedByteBuffer.force(); - } - - public void shutdown() { this.flush(); @@ -81,6 +88,14 @@ public void shutdown() { } + public void flush() { + this.mappedByteBuffer.putLong(0, this.physicMsgTimestamp); + this.mappedByteBuffer.putLong(8, this.logicsMsgTimestamp); + this.mappedByteBuffer.putLong(16, this.indexMsgTimestamp); + this.mappedByteBuffer.force(); + } + + public long getPhysicMsgTimestamp() { return physicMsgTimestamp; } diff --git a/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/StoreStatsService.java b/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/StoreStatsService.java index c12459f0..5e567770 100644 --- a/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/StoreStatsService.java +++ b/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/StoreStatsService.java @@ -1,92 +1,83 @@ /** - * $Id: StoreStatsService.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.store; import java.text.MessageFormat; import java.util.HashMap; import java.util.LinkedList; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.locks.ReentrantLock; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.alibaba.rocketmq.common.MixAll; import com.alibaba.rocketmq.common.ServiceThread; +import com.alibaba.rocketmq.common.constant.LoggerName; /** - * 洢ڲͳƷ + * 存储层内部统计服务 * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * @author shijia.wxr + * @since 2013-7-21 */ public class StoreStatsService extends ServiceThread { - static class CallSnapshot { - public final long timestamp; - public final long callTimesTotal; - - - public CallSnapshot(long timestamp, long callTimesTotal) { - this.timestamp = timestamp; - this.callTimesTotal = callTimesTotal; - } - - - public static double getTPS(final CallSnapshot begin, final CallSnapshot end) { - long total = end.callTimesTotal - begin.callTimesTotal; - Long time = end.timestamp - begin.timestamp; - - double tps = total / time.doubleValue(); - - return tps * 1000; - } - } - - private static final Logger log = LoggerFactory.getLogger(MixAll.StoreLoggerName); - // ʱ - private long messageStoreBootTimestamp = System.currentTimeMillis(); - // putMessageдϢʱʱ䣨λ룩 - private volatile long putMessageEntireTimeMax = 0; - // getMessageȡһϢʱʱ䣨λ룩 - private volatile long getMessageEntireTimeMax = 0; - - // for putMessageEntireTimeMax - private ReentrantLock lockPut = new ReentrantLock(); - // for getMessageEntireTimeMax - private ReentrantLock lockGet = new ReentrantLock(); - - // putMessageʧܴ + private static final Logger log = LoggerFactory.getLogger(LoggerName.StoreLoggerName); + // 采样频率,1秒钟采样一次 + private static final int FrequencyOfSampling = 1000; + // 采样最大记录数,超过则将之前的删除掉 + private static final int MaxRecordsOfSampling = 60 * 10; + // 打印TPS数据间隔时间,单位秒,1分钟 + private static int PrintTPSInterval = 60 * 1; + // putMessage,失败次数 private final AtomicLong putMessageFailedTimes = new AtomicLong(0); - // putMessage - private final AtomicLong putMessageTimesTotal = new AtomicLong(0); - // getMessage + // putMessage,调用总数 + private final Map putMessageTopicTimesTotal = + new ConcurrentHashMap(128); + // putMessage,Message Size Total + private final Map putMessageTopicSizeTotal = + new ConcurrentHashMap(128); + // getMessage,调用总数 private final AtomicLong getMessageTimesTotalFound = new AtomicLong(0); private final AtomicLong getMessageTransferedMsgCount = new AtomicLong(0); private final AtomicLong getMessageTimesTotalMiss = new AtomicLong(0); - // putMessageMessage Size Total - private final AtomicLong putMessageSizeTotal = new AtomicLong(0); - // putMessageʱֲ + // putMessage,耗时分布 private final AtomicLong[] putMessageDistributeTime = new AtomicLong[7]; - // DispatchMessageServiceֵ - private volatile long dispatchMaxBuffer = 0; - - // Ƶʣ1Ӳһ - private static final int FrequencyOfSampling = 1000; - // ¼֮ǰɾ - private static final int MaxRecordsOfSampling = 60 * 10; - // Բ̼߳ - private ReentrantLock lockSampling = new ReentrantLock(); - - // put10Ӳ + // put最近10分钟采样 private final LinkedList putTimesList = new LinkedList(); - // get10Ӳ + // get最近10分钟采样 private final LinkedList getTimesFoundList = new LinkedList(); private final LinkedList getTimesMissList = new LinkedList(); private final LinkedList transferedMsgCountList = new LinkedList(); - - // ӡTPSݼʱ䣬λ룬1 - private static int PrintTPSInterval = 60 * 1; + // 启动时间 + private long messageStoreBootTimestamp = System.currentTimeMillis(); + // putMessage,写入整个消息耗时,含加锁竟争时间(单位毫秒) + private volatile long putMessageEntireTimeMax = 0; + // getMessage,读取一批消息耗时,含加锁竟争时间(单位毫秒) + private volatile long getMessageEntireTimeMax = 0; + // for putMessageEntireTimeMax + private ReentrantLock lockPut = new ReentrantLock(); + // for getMessageEntireTimeMax + private ReentrantLock lockGet = new ReentrantLock(); + // DispatchMessageService,缓冲区最大值 + private volatile long dispatchMaxBuffer = 0; + // 针对采样线程加锁 + private ReentrantLock lockSampling = new ReentrantLock(); private long lastPrintTimestamp = System.currentTimeMillis(); @@ -103,31 +94,31 @@ public long getPutMessageEntireTimeMax() { public void setPutMessageEntireTimeMax(long value) { - // ΢ + // 微秒 if (value <= 0) { this.putMessageDistributeTime[0].incrementAndGet(); } - // + // 几毫秒 else if (value < 10) { this.putMessageDistributeTime[1].incrementAndGet(); } - // ʮ + // 几十毫秒 else if (value < 100) { this.putMessageDistributeTime[2].incrementAndGet(); } - // ٺ루500ڣ + // 几百毫秒(500毫秒以内) else if (value < 500) { this.putMessageDistributeTime[3].incrementAndGet(); } - // ٺ루500ϣ + // 几百毫秒(500毫秒以上) else if (value < 1000) { this.putMessageDistributeTime[4].incrementAndGet(); } - // + // 几秒 else if (value < 10000) { this.putMessageDistributeTime[5].incrementAndGet(); } - // 10 + // 大等于10秒 else { this.putMessageDistributeTime[6].incrementAndGet(); } @@ -156,16 +147,6 @@ public void setGetMessageEntireTimeMax(long value) { } - public AtomicLong getPutMessageTimesTotal() { - return putMessageTimesTotal; - } - - - public AtomicLong getPutMessageSizeTotal() { - return putMessageSizeTotal; - } - - public long getDispatchMaxBuffer() { return dispatchMaxBuffer; } @@ -176,41 +157,10 @@ public void setDispatchMaxBuffer(long value) { } - private String getPutMessageDistributeTimeStringInfo(Long total) { - final StringBuilder sb = new StringBuilder(512); - - for (AtomicLong i : this.putMessageDistributeTime) { - long value = i.get(); - double ratio = value / total.doubleValue(); - sb.append("\r\n\t\t"); - sb.append(value + "(" + (ratio * 100) + "%)"); - } - - return sb.toString(); - } - - - private String getFormatRuntime() { - final long MILLISECOND = 1; - final long SECOND = 1000 * MILLISECOND; - final long MINUTE = 60 * SECOND; - final long HOUR = 60 * MINUTE; - final long DAY = 24 * HOUR; - final MessageFormat TIME = new MessageFormat("[ {0} days, {1} hours, {2} minutes, {3} seconds ]"); - - long time = System.currentTimeMillis() - this.messageStoreBootTimestamp; - long days = time / DAY; - long hours = (time % DAY) / HOUR; - long minutes = (time % HOUR) / MINUTE; - long seconds = (time % MINUTE) / SECOND; - return TIME.format(new Long[] { days, hours, minutes, seconds }); - } - - @Override public String toString() { final StringBuilder sb = new StringBuilder(1024); - Long totalTimes = this.putMessageTimesTotal.get(); + Long totalTimes = getPutMessageTimesTotal(); if (0 == totalTimes) { totalTimes = 1L; } @@ -218,9 +168,10 @@ public String toString() { sb.append("\truntime: " + this.getFormatRuntime() + "\r\n"); sb.append("\tputMessageEntireTimeMax: " + this.putMessageEntireTimeMax + "\r\n"); sb.append("\tputMessageTimesTotal: " + totalTimes + "\r\n"); - sb.append("\tputMessageSizeTotal: " + this.putMessageSizeTotal.get() + "\r\n"); - sb.append("\tputMessageDistributeTime: " + this.getPutMessageDistributeTimeStringInfo(totalTimes) + "\r\n"); - sb.append("\tputMessageAverageSize: " + (this.putMessageSizeTotal.get() / totalTimes.doubleValue()) + sb.append("\tputMessageSizeTotal: " + this.getPutMessageSizeTotal() + "\r\n"); + sb.append("\tputMessageDistributeTime: " + this.getPutMessageDistributeTimeStringInfo(totalTimes) + + "\r\n"); + sb.append("\tputMessageAverageSize: " + (this.getPutMessageSizeTotal() / totalTimes.doubleValue()) + "\r\n"); sb.append("\tdispatchMaxBuffer: " + this.dispatchMaxBuffer + "\r\n"); sb.append("\tgetMessageEntireTimeMax: " + this.getMessageEntireTimeMax + "\r\n"); @@ -233,132 +184,105 @@ public String toString() { } - public HashMap getRuntimeInfo() { - HashMap result = new HashMap(64); - - Long totalTimes = this.putMessageTimesTotal.get(); - if (0 == totalTimes) { - totalTimes = 1L; - } - - result.put("bootimestamp", String.valueOf(this.messageStoreBootTimestamp)); - result.put("runtime", this.getFormatRuntime()); - result.put("putMessageEntireTimeMax", String.valueOf(this.putMessageEntireTimeMax)); - result.put("putMessageAverageSize", - String.valueOf((this.putMessageSizeTotal.get() / totalTimes.doubleValue()))); - result.put("dispatchMaxBuffer", String.valueOf(this.dispatchMaxBuffer)); - - return result; - } - - - private void sampling() { - this.lockSampling.lock(); - - this.putTimesList.add(new CallSnapshot(System.currentTimeMillis(), this.putMessageTimesTotal.get())); - if (this.putTimesList.size() > (MaxRecordsOfSampling + 1)) { - this.putTimesList.removeFirst(); - } - - this.getTimesFoundList.add(new CallSnapshot(System.currentTimeMillis(), this.getMessageTimesTotalFound - .get())); - if (this.getTimesFoundList.size() > (MaxRecordsOfSampling + 1)) { - this.getTimesFoundList.removeFirst(); - } - - this.getTimesMissList - .add(new CallSnapshot(System.currentTimeMillis(), this.getMessageTimesTotalMiss.get())); - if (this.getTimesMissList.size() > (MaxRecordsOfSampling + 1)) { - this.getTimesMissList.removeFirst(); - } + private String getPutMessageDistributeTimeStringInfo(Long total) { + final StringBuilder sb = new StringBuilder(512); - this.transferedMsgCountList.add(new CallSnapshot(System.currentTimeMillis(), - this.getMessageTransferedMsgCount.get())); - if (this.transferedMsgCountList.size() > (MaxRecordsOfSampling + 1)) { - this.transferedMsgCountList.removeFirst(); + for (AtomicLong i : this.putMessageDistributeTime) { + long value = i.get(); + double ratio = value / total.doubleValue(); + sb.append("\r\n\t\t"); + sb.append(value + "(" + (ratio * 100) + "%)"); } - this.lockSampling.unlock(); + return sb.toString(); } - private String getPutTps(int time) { - String result = ""; - this.lockSampling.lock(); - CallSnapshot last = this.putTimesList.getLast(); - - if (this.putTimesList.size() > time) { - CallSnapshot lastBefore = this.putTimesList.get(this.putTimesList.size() - (time + 1)); - result += CallSnapshot.getTPS(lastBefore, last); - } - - this.lockSampling.unlock(); + private String getFormatRuntime() { + final long MILLISECOND = 1; + final long SECOND = 1000 * MILLISECOND; + final long MINUTE = 60 * SECOND; + final long HOUR = 60 * MINUTE; + final long DAY = 24 * HOUR; + final MessageFormat TIME = new MessageFormat("[ {0} days, {1} hours, {2} minutes, {3} seconds ]"); - return result; + long time = System.currentTimeMillis() - this.messageStoreBootTimestamp; + long days = time / DAY; + long hours = (time % DAY) / HOUR; + long minutes = (time % HOUR) / MINUTE; + long seconds = (time % MINUTE) / SECOND; + return TIME.format(new Long[] { days, hours, minutes, seconds }); } private String getPutTps() { StringBuilder sb = new StringBuilder(); - // 10 + // 10秒钟 sb.append(this.getPutTps(10)); sb.append(" "); - // 1 + // 1分钟 sb.append(this.getPutTps(60)); sb.append(" "); - // 10 + // 10分钟 sb.append(this.getPutTps(600)); return sb.toString(); } - private String getGetFoundTps(int time) { + private String getPutTps(int time) { String result = ""; this.lockSampling.lock(); - CallSnapshot last = this.getTimesFoundList.getLast(); + try { + CallSnapshot last = this.putTimesList.getLast(); - if (this.getTimesFoundList.size() > time) { - CallSnapshot lastBefore = this.getTimesFoundList.get(this.getTimesFoundList.size() - (time + 1)); - result += CallSnapshot.getTPS(lastBefore, last); - } - - this.lockSampling.unlock(); + if (this.putTimesList.size() > time) { + CallSnapshot lastBefore = this.putTimesList.get(this.putTimesList.size() - (time + 1)); + result += CallSnapshot.getTPS(lastBefore, last); + } + } + finally { + this.lockSampling.unlock(); + } return result; } private String getGetFoundTps() { StringBuilder sb = new StringBuilder(); - // 10 + // 10秒钟 sb.append(this.getGetFoundTps(10)); sb.append(" "); - // 1 + // 1分钟 sb.append(this.getGetFoundTps(60)); sb.append(" "); - // 10 + // 10分钟 sb.append(this.getGetFoundTps(600)); return sb.toString(); } - private String getGetMissTps(int time) { + private String getGetFoundTps(int time) { String result = ""; this.lockSampling.lock(); - CallSnapshot last = this.getTimesMissList.getLast(); + try { + CallSnapshot last = this.getTimesFoundList.getLast(); - if (this.getTimesMissList.size() > time) { - CallSnapshot lastBefore = this.getTimesMissList.get(this.getTimesMissList.size() - (time + 1)); - result += CallSnapshot.getTPS(lastBefore, last); + if (this.getTimesFoundList.size() > time) { + CallSnapshot lastBefore = + this.getTimesFoundList.get(this.getTimesFoundList.size() - (time + 1)); + result += CallSnapshot.getTPS(lastBefore, last); + } + } + finally { + this.lockSampling.unlock(); } - - this.lockSampling.unlock(); return result; } @@ -366,33 +290,37 @@ private String getGetMissTps(int time) { private String getGetMissTps() { StringBuilder sb = new StringBuilder(); - // 10 + // 10秒钟 sb.append(this.getGetMissTps(10)); sb.append(" "); - // 1 + // 1分钟 sb.append(this.getGetMissTps(60)); sb.append(" "); - // 10 + // 10分钟 sb.append(this.getGetMissTps(600)); return sb.toString(); } - private String getGetTransferedTps(int time) { + private String getGetMissTps(int time) { String result = ""; this.lockSampling.lock(); - CallSnapshot last = this.transferedMsgCountList.getLast(); + try { + CallSnapshot last = this.getTimesMissList.getLast(); - if (this.transferedMsgCountList.size() > time) { - CallSnapshot lastBefore = - this.transferedMsgCountList.get(this.transferedMsgCountList.size() - (time + 1)); - result += CallSnapshot.getTPS(lastBefore, last); - } + if (this.getTimesMissList.size() > time) { + CallSnapshot lastBefore = + this.getTimesMissList.get(this.getTimesMissList.size() - (time + 1)); + result += CallSnapshot.getTPS(lastBefore, last); + } - this.lockSampling.unlock(); + } + finally { + this.lockSampling.unlock(); + } return result; } @@ -400,80 +328,136 @@ private String getGetTransferedTps(int time) { private String getGetTransferedTps() { StringBuilder sb = new StringBuilder(); - // 10 + // 10秒钟 sb.append(this.getGetTransferedTps(10)); sb.append(" "); - // 1 + // 1分钟 sb.append(this.getGetTransferedTps(60)); sb.append(" "); - // 10 + // 10分钟 sb.append(this.getGetTransferedTps(600)); return sb.toString(); } - private String getGetTotalTps(int time) { + private String getGetTransferedTps(int time) { + String result = ""; this.lockSampling.lock(); - double found = 0; - double miss = 0; - { - CallSnapshot last = this.getTimesFoundList.getLast(); + try { + CallSnapshot last = this.transferedMsgCountList.getLast(); - if (this.getTimesFoundList.size() > time) { - CallSnapshot lastBefore = this.getTimesFoundList.get(this.getTimesFoundList.size() - (time + 1)); - found = CallSnapshot.getTPS(lastBefore, last); + if (this.transferedMsgCountList.size() > time) { + CallSnapshot lastBefore = + this.transferedMsgCountList.get(this.transferedMsgCountList.size() - (time + 1)); + result += CallSnapshot.getTPS(lastBefore, last); } - } - { - CallSnapshot last = this.getTimesMissList.getLast(); - if (this.getTimesMissList.size() > time) { - CallSnapshot lastBefore = this.getTimesMissList.get(this.getTimesMissList.size() - (time + 1)); - miss = CallSnapshot.getTPS(lastBefore, last); - } + } + finally { + this.lockSampling.unlock(); } - this.lockSampling.unlock(); - - return Double.toString(found + miss); + return result; } private String getGetTotalTps() { StringBuilder sb = new StringBuilder(); - // 10 + // 10秒钟 sb.append(this.getGetTotalTps(10)); sb.append(" "); - // 1 + // 1分钟 sb.append(this.getGetTotalTps(60)); sb.append(" "); - // 10 + // 10分钟 sb.append(this.getGetTotalTps(600)); return sb.toString(); } - /** - * 1ӴӡһTPS - */ - private void printTps() { - if (System.currentTimeMillis() > (this.lastPrintTimestamp + PrintTPSInterval * 1000)) { - this.lastPrintTimestamp = System.currentTimeMillis(); + private String getGetTotalTps(int time) { + this.lockSampling.lock(); + double found = 0; + double miss = 0; + try { + { + CallSnapshot last = this.getTimesFoundList.getLast(); + + if (this.getTimesFoundList.size() > time) { + CallSnapshot lastBefore = + this.getTimesFoundList.get(this.getTimesFoundList.size() - (time + 1)); + found = CallSnapshot.getTPS(lastBefore, last); + } + } + { + CallSnapshot last = this.getTimesMissList.getLast(); + + if (this.getTimesMissList.size() > time) { + CallSnapshot lastBefore = + this.getTimesMissList.get(this.getTimesMissList.size() - (time + 1)); + miss = CallSnapshot.getTPS(lastBefore, last); + } + } - log.info("put_tps {}", this.getPutTps(PrintTPSInterval)); + } + finally { + this.lockSampling.unlock(); + } - log.info("get_found_tps {}", this.getGetFoundTps(PrintTPSInterval)); + return Double.toString(found + miss); + } - log.info("get_miss_tps {}", this.getGetMissTps(PrintTPSInterval)); - log.info("get_transfered_tps {}", this.getGetTransferedTps(PrintTPSInterval)); + public long getPutMessageTimesTotal() { + long rs = 0; + for (AtomicLong data : putMessageTopicTimesTotal.values()) { + rs += data.get(); } + return rs; + } + + + public long getPutMessageSizeTotal() { + long rs = 0; + for (AtomicLong data : putMessageTopicSizeTotal.values()) { + rs += data.get(); + } + return rs; + } + + + public HashMap getRuntimeInfo() { + HashMap result = new HashMap(64); + + Long totalTimes = getPutMessageTimesTotal(); + if (0 == totalTimes) { + totalTimes = 1L; + } + + result.put("bootTimestamp", String.valueOf(this.messageStoreBootTimestamp)); + result.put("runtime", this.getFormatRuntime()); + result.put("putMessageEntireTimeMax", String.valueOf(this.putMessageEntireTimeMax)); + result.put("putMessageTimesTotal", String.valueOf(totalTimes)); + result.put("putMessageSizeTotal", String.valueOf(this.getPutMessageSizeTotal())); + result.put("putMessageDistributeTime", + String.valueOf(this.getPutMessageDistributeTimeStringInfo(totalTimes))); + result.put("putMessageAverageSize", + String.valueOf((this.getPutMessageSizeTotal() / totalTimes.doubleValue()))); + result.put("dispatchMaxBuffer", String.valueOf(this.dispatchMaxBuffer)); + result.put("getMessageEntireTimeMax", String.valueOf(this.getMessageEntireTimeMax)); + result.put("putTps", String.valueOf(this.getPutTps())); + result.put("getFoundTps", String.valueOf(this.getGetFoundTps())); + result.put("getMissTps", String.valueOf(this.getGetMissTps())); + result.put("getTotalTps", String.valueOf(this.getGetTotalTps())); + result.put("getTransferedTps", String.valueOf(this.getGetTransferedTps())); + + return result; } @@ -497,6 +481,57 @@ public void run() { } + private void sampling() { + this.lockSampling.lock(); + try { + this.putTimesList.add(new CallSnapshot(System.currentTimeMillis(), getPutMessageTimesTotal())); + if (this.putTimesList.size() > (MaxRecordsOfSampling + 1)) { + this.putTimesList.removeFirst(); + } + + this.getTimesFoundList.add(new CallSnapshot(System.currentTimeMillis(), + this.getMessageTimesTotalFound.get())); + if (this.getTimesFoundList.size() > (MaxRecordsOfSampling + 1)) { + this.getTimesFoundList.removeFirst(); + } + + this.getTimesMissList.add(new CallSnapshot(System.currentTimeMillis(), + this.getMessageTimesTotalMiss.get())); + if (this.getTimesMissList.size() > (MaxRecordsOfSampling + 1)) { + this.getTimesMissList.removeFirst(); + } + + this.transferedMsgCountList.add(new CallSnapshot(System.currentTimeMillis(), + this.getMessageTransferedMsgCount.get())); + if (this.transferedMsgCountList.size() > (MaxRecordsOfSampling + 1)) { + this.transferedMsgCountList.removeFirst(); + } + + } + finally { + this.lockSampling.unlock(); + } + } + + + /** + * 1分钟打印一次TPS + */ + private void printTps() { + if (System.currentTimeMillis() > (this.lastPrintTimestamp + PrintTPSInterval * 1000)) { + this.lastPrintTimestamp = System.currentTimeMillis(); + + log.info("put_tps {}", this.getPutTps(PrintTPSInterval)); + + log.info("get_found_tps {}", this.getGetFoundTps(PrintTPSInterval)); + + log.info("get_miss_tps {}", this.getGetMissTps(PrintTPSInterval)); + + log.info("get_transfered_tps {}", this.getGetTransferedTps(PrintTPSInterval)); + } + } + + @Override public String getServiceName() { return StoreStatsService.class.getSimpleName(); @@ -521,4 +556,55 @@ public AtomicLong getGetMessageTransferedMsgCount() { public AtomicLong getPutMessageFailedTimes() { return putMessageFailedTimes; } + + + public AtomicLong getSinglePutMessageTopicSizeTotal(String topic) { + AtomicLong rs = putMessageTopicSizeTotal.get(topic); + if (null == rs) { + rs = new AtomicLong(0); + putMessageTopicSizeTotal.put(topic, rs); + } + return rs; + } + + + public AtomicLong getSinglePutMessageTopicTimesTotal(String topic) { + AtomicLong rs = putMessageTopicTimesTotal.get(topic); + if (null == rs) { + rs = new AtomicLong(0); + putMessageTopicTimesTotal.put(topic, rs); + } + return rs; + } + + + public Map getPutMessageTopicTimesTotal() { + return putMessageTopicTimesTotal; + } + + + public Map getPutMessageTopicSizeTotal() { + return putMessageTopicSizeTotal; + } + + static class CallSnapshot { + public final long timestamp; + public final long callTimesTotal; + + + public CallSnapshot(long timestamp, long callTimesTotal) { + this.timestamp = timestamp; + this.callTimesTotal = callTimesTotal; + } + + + public static double getTPS(final CallSnapshot begin, final CallSnapshot end) { + long total = end.callTimesTotal - begin.callTimesTotal; + Long time = end.timestamp - begin.timestamp; + + double tps = total / time.doubleValue(); + + return tps * 1000; + } + } } diff --git a/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/StoreUtil.java b/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/StoreUtil.java new file mode 100644 index 00000000..9509882b --- /dev/null +++ b/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/StoreUtil.java @@ -0,0 +1,40 @@ +/** + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.rocketmq.store; + +import java.lang.management.ManagementFactory; +import java.lang.management.OperatingSystemMXBean; + + +/** + * @author shijia.wxr + * @since 13-8-3 + */ +public class StoreUtil { + public static final long TotalPhysicalMemorySize = getTotalPhysicalMemorySize(); + + + @SuppressWarnings("restriction") + public static long getTotalPhysicalMemorySize() { + long physicalTotal = 1024 * 1024 * 1024 * 24; + OperatingSystemMXBean osmxb = ManagementFactory.getOperatingSystemMXBean(); + if (osmxb instanceof com.sun.management.OperatingSystemMXBean) { + physicalTotal = ((com.sun.management.OperatingSystemMXBean) osmxb).getTotalPhysicalMemorySize(); + } + + return physicalTotal; + } +} diff --git a/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/config/BrokerRole.java b/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/config/BrokerRole.java index cd6619b1..51f4afc7 100644 --- a/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/config/BrokerRole.java +++ b/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/config/BrokerRole.java @@ -1,17 +1,30 @@ /** - * $Id: BrokerRole.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.store.config; /** - * Brokerɫ + * Broker角色 * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * @author shijia.wxr + * @since 2013-7-21 */ public enum BrokerRole { - // 첽Master + // 异步复制Master ASYNC_MASTER, - // ͬ˫дMaster + // 同步双写Master SYNC_MASTER, // Slave SLAVE diff --git a/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/config/FlushDiskType.java b/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/config/FlushDiskType.java index 8bc9add2..5773a25e 100644 --- a/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/config/FlushDiskType.java +++ b/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/config/FlushDiskType.java @@ -1,20 +1,33 @@ /** - * $Id: FlushDiskType.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.store.config; /** - * ˢ̷ʽ + * 刷盘方式 * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * @author shijia.wxr + * @since 2013-7-21 */ public enum FlushDiskType { /** - * ͬˢ + * 同步刷盘 */ SYNC_FLUSH, /** - * 첽ˢ + * 异步刷盘 */ ASYNC_FLUSH } diff --git a/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/config/MessageStoreConfig.java b/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/config/MessageStoreConfig.java index 9b5c2c33..c530f543 100644 --- a/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/config/MessageStoreConfig.java +++ b/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/config/MessageStoreConfig.java @@ -1,122 +1,157 @@ /** - * $Id: MessageStoreConfig.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.store.config; import java.io.File; +import com.alibaba.rocketmq.common.annotation.ImportantField; import com.alibaba.rocketmq.store.ConsumeQueue; import com.alibaba.rocketmq.store.transaction.TransactionStateService; /** - * 洢ļ + * 存储层配置文件类 * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * @author shijia.wxr + * @since 2013-7-21 */ public class MessageStoreConfig { - // CommitLog洢Ŀ¼ + // CommitLog存储目录 + @ImportantField private String storePathCommitLog = System.getProperty("user.home") + File.separator + "store" + File.separator + "commitlog"; - // ConsumeQueue洢Ŀ¼ + // ConsumeQueue存储目录 + @ImportantField private String storePathConsumeQueue = System.getProperty("user.home") + File.separator + "store" + File.separator + "consumequeue"; - // ļ洢Ŀ¼ - private String storePathIndex = System.getProperty("user.home") + File.separator + "store" + File.separator - + "index"; - // 쳣˳ļ - private String storeCheckpoint = System.getProperty("user.home") + File.separator + "store" + File.separator - + "storeCheckpoint"; - // 쳣˳ļ + // 索引文件存储目录 + @ImportantField + private String storePathIndex = System.getProperty("user.home") + File.separator + "store" + + File.separator + "index"; + // 异常退出产生的文件 + @ImportantField + private String storeCheckpoint = System.getProperty("user.home") + File.separator + "store" + + File.separator + "checkpoint"; + // 异常退出产生的文件 + @ImportantField private String abortFile = System.getProperty("user.home") + File.separator + "store" + File.separator - + "storeAbort"; - // CommitLogÿļС 1G + + "abort"; + // CommitLog每个文件大小 1G private int mapedFileSizeCommitLog = 1024 * 1024 * 1024; - // ConsumeQueueÿļС Ĭϴ洢50WϢ - private int mapedFileSizeConsumeQueue = 500000 * ConsumeQueue.CQStoreUnitSize; - // CommitLogˢ̼ʱ䣨λ룩 + // ConsumeQueue每个文件大小 默认存储30W条消息 + private int mapedFileSizeConsumeQueue = 300000 * ConsumeQueue.CQStoreUnitSize; + // CommitLog刷盘间隔时间(单位毫秒) private int flushIntervalCommitLog = 1000; - // ConsumeQueueˢ̼ʱ䣨λ룩 + // ConsumeQueue刷盘间隔时间(单位毫秒) private int flushIntervalConsumeQueue = 1000; - // Դʱ䣨λ룩 + // 清理资源间隔时间(单位毫秒) private int cleanResourceInterval = 10000; - // ɾCommitLogļļʱ䣨λ룩 + // 删除多个CommitLog文件的间隔时间(单位毫秒) private int deleteCommitLogFilesInterval = 100; - // ɾConsumeQueueļļʱ䣨λ룩 + // 删除多个ConsumeQueue文件的间隔时间(单位毫秒) private int deleteConsumeQueueFilesInterval = 100; - // ǿɾļʱ䣨λ룩 + // 强制删除文件间隔时间(单位毫秒) private int destroyMapedFileIntervalForcibly = 1000 * 120; - // ڼHangedļʱ䣨λ룩 + // 定期检查Hanged文件间隔时间(单位毫秒) private int redeleteHangedFileInterval = 1000 * 120; - // ʱɾļ, Ĭ賿4ɾļ + // 何时触发删除文件, 默认凌晨4点删除文件 + @ImportantField private String deleteWhen = "04"; - // ̿ռʹ + // 磁盘空间最大使用率 private int diskMaxUsedSpaceRatio = 75; - // ļʱ䣨λСʱ - private int fileReservedTime = 12; - - // дϢConsumeQueueˮλʼ + // 文件保留时间(单位小时) + @ImportantField + private int fileReservedTime = 48; + // 写消息索引到ConsumeQueue,缓冲区高水位,超过则开始流控 private int putMsgIndexHightWater = 600000; - // ϢСĬ512K + // 最大消息大小,默认512K private int maxMessageSize = 1024 * 512; - // ʱǷУCRC + // 重启时,是否校验CRC private boolean checkCRCOnRecover = true; - // ˢCommitLogˢPAGE + // 刷CommitLog,至少刷几个PAGE private int flushCommitLogLeastPages = 4; - // ˢConsumeQueueˢPAGE + // 刷ConsumeQueue,至少刷几个PAGE private int flushConsumeQueueLeastPages = 2; - // ˢCommitLogˢ̼ʱ + // 刷CommitLog,彻底刷盘间隔时间 private int flushCommitLogThoroughInterval = 1000 * 10; - // ˢConsumeQueueˢ̼ʱ + // 刷ConsumeQueue,彻底刷盘间隔时间 private int flushConsumeQueueThoroughInterval = 1000 * 60; - // ȡϢֽϢڴ + // 最大被拉取的消息字节数,消息在内存 + @ImportantField private int maxTransferBytesOnMessageInMemory = 1024 * 256; - // ȡϢϢڴ + // 最大被拉取的消息个数,消息在内存 + @ImportantField private int maxTransferCountOnMessageInMemory = 32; - // ȡϢֽϢڴ + // 最大被拉取的消息字节数,消息在磁盘 + @ImportantField private int maxTransferBytesOnMessageInDisk = 1024 * 64; - // ȡϢϢڴ + // 最大被拉取的消息个数,消息在磁盘 + @ImportantField private int maxTransferCountOnMessageInDisk = 8; - // Ϣڴ - private int accessMessageInMemoryMaxRatio = 30; - - // ǷϢ + // 命中消息在内存的最大比例 + @ImportantField + private int accessMessageInMemoryMaxRatio = 40; + // 是否开启消息索引功能 + @ImportantField private boolean messageIndexEnable = true; private int maxHashSlotNum = 5000000; private int maxIndexNum = 5000000 * 4; private int maxMsgsNumBatch = 32; - - // HA + // 是否使用安全的消息索引功能,即可靠模式。 + // 可靠模式下,异常宕机恢复慢 + // 非可靠模式下,异常宕机恢复快 + @ImportantField + private boolean messageIndexSafe = false; + // HA功能 private int haListenPort = 10912; private int haSendHeartbeatInterval = 1000 * 5; private int haHousekeepingInterval = 1000 * 20; private int haTransferBatchSize = 1024 * 32; - // ãNameServerȡMasterַȻַͨҵHAַ - private String masterAddress = null; - - // SlaveMasterֵΪ쳣 + // 如果不设置,则从NameServer获取Master HA服务地址 + @ImportantField + private String haMasterAddress = null; + // Slave落后Master超过此值,则认为存在异常 private int haSlaveFallbehindMax = 1024 * 1024 * 256; - + @ImportantField private BrokerRole brokerRole = BrokerRole.ASYNC_MASTER; + @ImportantField private FlushDiskType flushDiskType = FlushDiskType.ASYNC_FLUSH; - - // ͬˢ̳ʱʱ + // 同步刷盘超时时间 private int syncFlushTimeout = 1000 * 5; - - // ʱϢ - private String messageDelayLevel = "1s 5s 10s 30s 1m 5m 10m 30m 1h 2h 6h 12h 1d"; - private long flushDelayOffsetInterval = 1000 * 5; + // 定时消息相关 + private String messageDelayLevel = "1s 5s 10s 30s 1m 2m 3m 4m 5m 6m 7m 8m 9m 10m 20m 30m"; + private long flushDelayOffsetInterval = 1000 * 10; private String delayOffsetStorePath = System.getProperty("user.home") + File.separator + "store" - + File.separator + "delayOffset.properties"; - - // ֲʽ + + File.separator + "config" + File.separator + "delayOffset.json"; + // 分布式事务配置 private String tranStateTableStorePath = System.getProperty("user.home") + File.separator + "store" + File.separator + "transaction" + File.separator + "statetable"; private int tranStateTableMapedFileSize = 2000000 * TransactionStateService.TSStoreUnitSize; - private String tranRedoLogStorePath = System.getProperty("user.home") + File.separator + "store" + File.separator + "transaction" + File.separator + "redolog"; private int tranRedoLogMapedFileSize = 2000000 * ConsumeQueue.CQStoreUnitSize; + // 事务回查至少间隔时间 + private long checkTransactionMessageAtleastInterval = 1000 * 60; + // 事务回查定时间隔时间 + private long checkTransactionMessageTimerInterval = 1000 * 60; + // 是否开启事务Check过程,双十一时,可以关闭 + private boolean checkTransactionMessageEnable = true; + // 磁盘空间超过90%警戒水位,自动开始删除文件 + @ImportantField + private boolean cleanFileForciblyEnable = true; public int getMapedFileSizeCommitLog() { @@ -130,7 +165,7 @@ public void setMapedFileSizeCommitLog(int mapedFileSizeCommitLog) { public int getMapedFileSizeConsumeQueue() { - // ˴Ҫȡ + // 此处需要向上取整 int factor = (int) Math.ceil(this.mapedFileSizeConsumeQueue / (ConsumeQueue.CQStoreUnitSize * 1.0)); return (int) (factor * ConsumeQueue.CQStoreUnitSize); } @@ -552,13 +587,13 @@ public void setSyncFlushTimeout(int syncFlushTimeout) { } - public String getMasterAddress() { - return masterAddress; + public String getHaMasterAddress() { + return haMasterAddress; } - public void setMasterAddress(String masterAddress) { - this.masterAddress = masterAddress; + public void setHaMasterAddress(String haMasterAddress) { + this.haMasterAddress = haMasterAddress; } @@ -630,4 +665,54 @@ public int getTranRedoLogMapedFileSize() { public void setTranRedoLogMapedFileSize(int tranRedoLogMapedFileSize) { this.tranRedoLogMapedFileSize = tranRedoLogMapedFileSize; } + + + public long getCheckTransactionMessageAtleastInterval() { + return checkTransactionMessageAtleastInterval; + } + + + public void setCheckTransactionMessageAtleastInterval(long checkTransactionMessageAtleastInterval) { + this.checkTransactionMessageAtleastInterval = checkTransactionMessageAtleastInterval; + } + + + public long getCheckTransactionMessageTimerInterval() { + return checkTransactionMessageTimerInterval; + } + + + public void setCheckTransactionMessageTimerInterval(long checkTransactionMessageTimerInterval) { + this.checkTransactionMessageTimerInterval = checkTransactionMessageTimerInterval; + } + + + public boolean isCleanFileForciblyEnable() { + return cleanFileForciblyEnable; + } + + + public void setCleanFileForciblyEnable(boolean cleanFileForciblyEnable) { + this.cleanFileForciblyEnable = cleanFileForciblyEnable; + } + + + public boolean isCheckTransactionMessageEnable() { + return checkTransactionMessageEnable; + } + + + public void setCheckTransactionMessageEnable(boolean checkTransactionMessageEnable) { + this.checkTransactionMessageEnable = checkTransactionMessageEnable; + } + + + public boolean isMessageIndexSafe() { + return messageIndexSafe; + } + + + public void setMessageIndexSafe(boolean messageIndexSafe) { + this.messageIndexSafe = messageIndexSafe; + } } diff --git a/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/ha/HAConnection.java b/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/ha/HAConnection.java index 552c7c43..6f5841dc 100644 --- a/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/ha/HAConnection.java +++ b/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/ha/HAConnection.java @@ -1,5 +1,17 @@ /** - * $Id: HAConnection.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.store.ha; @@ -12,36 +24,84 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.alibaba.rocketmq.common.MixAll; import com.alibaba.rocketmq.common.ServiceThread; +import com.alibaba.rocketmq.common.constant.LoggerName; import com.alibaba.rocketmq.remoting.common.RemotingUtil; import com.alibaba.rocketmq.store.SelectMapedBufferResult; /** - * HAMasterSlave PushݣSlaveӦ + * HA服务,Master用来向Slave Push数据,并接收Slave应答 * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * @author shijia.wxr + * @since 2013-7-21 */ public class HAConnection { - private static final Logger log = LoggerFactory.getLogger(MixAll.StoreLoggerName); - + private static final Logger log = LoggerFactory.getLogger(LoggerName.StoreLoggerName); private final HAService haService; private final SocketChannel socketChannel; private final String clientAddr; - private WriteSocketService writeSocketService; private ReadSocketService readSocketService; - - // Slave↑ʼ + // Slave请求从哪里开始拉数据 private volatile long slaveRequestOffset = -1; - // SlaveյݺӦOffset + // Slave收到数据后,应答Offset private volatile long slaveAckOffset = -1; + + public HAConnection(final HAService haService, final SocketChannel socketChannel) throws IOException { + this.haService = haService; + this.socketChannel = socketChannel; + this.clientAddr = this.socketChannel.socket().getRemoteSocketAddress().toString(); + this.socketChannel.configureBlocking(false); + this.socketChannel.socket().setSoLinger(false, -1); + this.socketChannel.socket().setTcpNoDelay(true); + this.socketChannel.socket().setReceiveBufferSize(1024 * 64); + this.socketChannel.socket().setSendBufferSize(1024 * 64); + this.writeSocketService = new WriteSocketService(this.socketChannel); + this.readSocketService = new ReadSocketService(this.socketChannel); + this.haService.getConnectionCount().incrementAndGet(); + } + + /** - * ȡSlaveһΪpush ack + * 向Slave传输数据协议
+ * 从Slave接收数据协议 + */ + + public void start() { + this.readSocketService.start(); + this.writeSocketService.start(); + } + + + public void shutdown() { + this.writeSocketService.shutdown(true); + this.readSocketService.shutdown(true); + this.close(); + } + + + public void close() { + if (this.socketChannel != null) { + try { + this.socketChannel.close(); + } + catch (IOException e) { + HAConnection.log.error("", e); + } + } + } + + + public SocketChannel getSocketChannel() { + return socketChannel; + } + + /** + * 读取Slave请求,一般为push ack * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * @author shijia.wxr */ class ReadSocketService extends ServiceThread { private static final int ReadMaxBufferSize = 1024 * 1024; @@ -56,11 +116,63 @@ public ReadSocketService(final SocketChannel socketChannel) throws IOException { this.selector = RemotingUtil.openSelector(); this.socketChannel = socketChannel; this.socketChannel.register(this.selector, SelectionKey.OP_READ); - // ߳ԶգҪ߳join + // 线程自动回收,不需要被其他线程join this.thread.setDaemon(true); } + @Override + public void run() { + HAConnection.log.info(this.getServiceName() + " service started"); + + while (!this.isStoped()) { + try { + this.selector.select(1000); + boolean ok = this.processReadEvent(); + if (!ok) { + HAConnection.log.error("processReadEvent error"); + break; + } + + // 检测心跳间隔时间,超过则强制断开 + long interval = + HAConnection.this.haService.getDefaultMessageStore().getSystemClock().now() + - this.lastReadTimestamp; + if (interval > HAConnection.this.haService.getDefaultMessageStore() + .getMessageStoreConfig().getHaHousekeepingInterval()) { + log.warn("ha housekeeping, found this connection[" + HAConnection.this.clientAddr + + "] expired, " + interval); + break; + } + } + catch (Exception e) { + HAConnection.log.error(this.getServiceName() + " service has exception.", e); + break; + } + } + + this.makeStop(); + + // 只有读线程需要执行 + HAConnection.this.haService.getConnectionCount().decrementAndGet(); + + SelectionKey sk = this.socketChannel.keyFor(this.selector); + if (sk != null) { + sk.cancel(); + } + + try { + this.selector.close(); + this.socketChannel.close(); + } + catch (IOException e) { + HAConnection.log.error("", e); + } + + HAConnection.log.info(this.getServiceName() + " service end"); + } + + private boolean processReadEvent() { int readSizeZeroTimes = 0; @@ -76,13 +188,13 @@ private boolean processReadEvent() { readSizeZeroTimes = 0; this.lastReadTimestamp = HAConnection.this.haService.getDefaultMessageStore().getSystemClock().now(); - // Slaveϴoffset + // 接收Slave上传的offset if ((this.byteBufferRead.position() - this.processPostion) >= 8) { int pos = this.byteBufferRead.position() - (this.byteBufferRead.position() % 8); long readOffset = this.byteBufferRead.getLong(pos - 8); this.processPostion = pos; - // Slave + // 处理Slave的请求 HAConnection.this.slaveAckOffset = readOffset; if (HAConnection.this.slaveRequestOffset < 0) { HAConnection.this.slaveRequestOffset = readOffset; @@ -90,7 +202,7 @@ private boolean processReadEvent() { + readOffset); } - // ֪ͨǰ߳ + // 通知前端线程 HAConnection.this.haService.notifyTransferSome(HAConnection.this.slaveAckOffset); } } @@ -114,58 +226,6 @@ else if (readSize == 0) { } - @Override - public void run() { - HAConnection.log.info(this.getServiceName() + " service started"); - - while (!this.isStoped()) { - try { - this.selector.select(1000); - boolean ok = this.processReadEvent(); - if (!ok) { - HAConnection.log.error("processReadEvent error"); - break; - } - - // ʱ䣬ǿƶϿ - long interval = - HAConnection.this.haService.getDefaultMessageStore().getSystemClock().now() - - this.lastReadTimestamp; - if (interval > HAConnection.this.haService.getDefaultMessageStore().getMessageStoreConfig() - .getHaHousekeepingInterval()) { - log.warn("ha housekeeping, found this connection[" + HAConnection.this.clientAddr - + "] expired, " + interval); - break; - } - } - catch (Exception e) { - HAConnection.log.error(this.getServiceName() + " service has exception.", e); - break; - } - } - - this.makeStop(); - - // ֻж߳Ҫִ - HAConnection.this.haService.getConnectionCount().decrementAndGet(); - - SelectionKey sk = this.socketChannel.keyFor(this.selector); - if (sk != null) { - sk.cancel(); - } - - try { - this.selector.close(); - this.socketChannel.close(); - } - catch (IOException e) { - HAConnection.log.error("", e); - } - - HAConnection.log.info(this.getServiceName() + " service end"); - } - - @Override public String getServiceName() { return ReadSocketService.class.getSimpleName(); @@ -173,24 +233,18 @@ public String getServiceName() { } /** - * SlaveЭ
- * SlaveЭ - */ - /** - * Slaveд + * 向Slave写入数据 * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * @author shijia.wxr */ class WriteSocketService extends ServiceThread { private final Selector selector; private final SocketChannel socketChannel; - private long nextTransferFromWhere = -1; - - // Ҫ + // 要传输的数据 private final int HEADER_SIZE = 8 + 4; private final ByteBuffer byteBufferHeader = ByteBuffer.allocate(HEADER_SIZE); + private long nextTransferFromWhere = -1; private SelectMapedBufferResult selectMapedBufferResult; - private boolean lastWriteOver = true; private long lastWriteTimestamp = System.currentTimeMillis(); @@ -216,8 +270,8 @@ public void run() { continue; } - // һδ䣬Ҫ↑ʼ - // SlaveûݣOffsetΪ0ômasterļһļʼ + // 第一次传输,需要计算从哪里开始 + // Slave如果本地没有数据,请求的Offset为0,那么master则从物理文件最后一个文件开始传送数据 if (-1 == this.nextTransferFromWhere) { if (0 == HAConnection.this.slaveRequestOffset) { long masterOffset = @@ -225,8 +279,9 @@ public void run() { .getMaxOffset(); masterOffset = masterOffset - - (masterOffset % HAConnection.this.haService.getDefaultMessageStore() - .getMessageStoreConfig().getMapedFileSizeCommitLog()); + - (masterOffset % HAConnection.this.haService + .getDefaultMessageStore().getMessageStoreConfig() + .getMapedFileSizeCommitLog()); if (masterOffset < 0) { masterOffset = 0; @@ -244,14 +299,14 @@ public void run() { } if (this.lastWriteOver) { - // ʱûзϢԷ + // 如果长时间没有发消息则尝试发心跳 long interval = HAConnection.this.haService.getDefaultMessageStore().getSystemClock().now() - this.lastWriteTimestamp; - if (interval > HAConnection.this.haService.getDefaultMessageStore().getMessageStoreConfig() - .getHaSendHeartbeatInterval()) { - // Slave + if (interval > HAConnection.this.haService.getDefaultMessageStore() + .getMessageStoreConfig().getHaSendHeartbeatInterval()) { + // 向Slave发送心跳 // Build Header this.byteBufferHeader.position(0); this.byteBufferHeader.limit(HEADER_SIZE); @@ -264,25 +319,25 @@ public void run() { continue; } } - // + // 继续传输 else { this.lastWriteOver = this.transferData(); if (!this.lastWriteOver) continue; } - // , - // selectResultḳֵthis.selectMapedBufferResult쳣Ҳ + // 传输数据, + // selectResult会赋值给this.selectMapedBufferResult,出现异常也会清理掉 SelectMapedBufferResult selectResult = HAConnection.this.haService.getDefaultMessageStore().getCommitLogData( this.nextTransferFromWhere); if (selectResult != null) { int size = selectResult.getSize(); - if (size > HAConnection.this.haService.getDefaultMessageStore().getMessageStoreConfig() - .getHaTransferBatchSize()) { + if (size > HAConnection.this.haService.getDefaultMessageStore() + .getMessageStoreConfig().getHaTransferBatchSize()) { size = - HAConnection.this.haService.getDefaultMessageStore().getMessageStoreConfig() - .getHaTransferBatchSize(); + HAConnection.this.haService.getDefaultMessageStore() + .getMessageStoreConfig().getHaTransferBatchSize(); } long thisOffset = this.nextTransferFromWhere; @@ -301,18 +356,18 @@ public void run() { this.lastWriteOver = this.transferData(); } else { - // ûݣȴ֪ͨ + // 没有数据,等待通知 HAConnection.this.haService.getWaitNotifyObject().allWaitForRunning(100); } } catch (Exception e) { - // ֻҪ׳쳣һ緢ӱϿԴ + // 只要抛出异常,一般是网络发生错误,连接必须断开,并清理资源 HAConnection.log.error(this.getServiceName() + " service has exception.", e); break; } } - // Դ + // 清理资源 if (this.selectMapedBufferResult != null) { this.selectMapedBufferResult.release(); } @@ -337,7 +392,7 @@ public void run() { /** - * ʾǷ + * 表示是否传输完成 */ private boolean transferData() throws Exception { int writeSizeZeroTimes = 0; @@ -409,49 +464,4 @@ public void shutdown() { super.shutdown(); } } - - - public HAConnection(final HAService haService, final SocketChannel socketChannel) throws IOException { - this.haService = haService; - this.socketChannel = socketChannel; - this.clientAddr = this.socketChannel.socket().getRemoteSocketAddress().toString(); - this.socketChannel.configureBlocking(false); - this.socketChannel.socket().setSoLinger(false, -1); - this.socketChannel.socket().setTcpNoDelay(true); - this.socketChannel.socket().setReceiveBufferSize(1024 * 64); - this.socketChannel.socket().setSendBufferSize(1024 * 64); - this.writeSocketService = new WriteSocketService(this.socketChannel); - this.readSocketService = new ReadSocketService(this.socketChannel); - this.haService.getConnectionCount().incrementAndGet(); - } - - - public void start() { - this.readSocketService.start(); - this.writeSocketService.start(); - } - - - public void shutdown() { - this.writeSocketService.shutdown(true); - this.readSocketService.shutdown(true); - this.close(); - } - - - public SocketChannel getSocketChannel() { - return socketChannel; - } - - - public void close() { - if (this.socketChannel != null) { - try { - this.socketChannel.close(); - } - catch (IOException e) { - HAConnection.log.error("", e); - } - } - } } diff --git a/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/ha/HAService.java b/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/ha/HAService.java index d17ebe22..ffcf9c40 100644 --- a/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/ha/HAService.java +++ b/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/ha/HAService.java @@ -1,5 +1,17 @@ /** - * $Id: HAService.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.store.ha; @@ -23,38 +35,151 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.alibaba.rocketmq.common.MixAll; import com.alibaba.rocketmq.common.ServiceThread; +import com.alibaba.rocketmq.common.constant.LoggerName; import com.alibaba.rocketmq.remoting.common.RemotingUtil; -import com.alibaba.rocketmq.store.DefaultMessageStore; import com.alibaba.rocketmq.store.CommitLog.GroupCommitRequest; +import com.alibaba.rocketmq.store.DefaultMessageStore; /** - * HA񣬸ͬ˫д첽ƹ + * HA服务,负责同步双写,异步复制功能 * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * @author shijia.wxr + * @since 2013-7-21 */ public class HAService { - private static final Logger log = LoggerFactory.getLogger(MixAll.StoreLoggerName); - // ͻӼ + private static final Logger log = LoggerFactory.getLogger(LoggerName.StoreLoggerName); + // 客户端连接计数 private final AtomicInteger connectionCount = new AtomicInteger(0); - // 洢ͻ + // 存储客户端连接 private final List connectionList = new LinkedList(); - // µSocket + // 接收新的Socket连接 private final AcceptSocketService acceptSocketService; - // 洢 + // 顶层存储对象 private final DefaultMessageStore defaultMessageStore; - // 첽֪ͨ + // 异步通知 private final WaitNotifyObject waitNotifyObject = new WaitNotifyObject(); - // д뵽SlaveOffset + // 写入到Slave的最大Offset private final AtomicLong push2SlaveMaxOffset = new AtomicLong(0); - // Ӹ֪ͨ + // 主从复制通知服务 private final GroupTransferService groupTransferService; - - // SlaveĶ + // Slave订阅对象 private final HAClient haClient; + + public HAService(final DefaultMessageStore defaultMessageStore) throws IOException { + this.defaultMessageStore = defaultMessageStore; + this.acceptSocketService = + new AcceptSocketService(defaultMessageStore.getMessageStoreConfig().getHaListenPort()); + this.groupTransferService = new GroupTransferService(); + this.haClient = new HAClient(); + } + + + public void updateMasterAddress(final String newAddr) { + if (this.haClient != null) { + this.haClient.updateMasterAddress(newAddr); + } + } + + + public void putRequest(final GroupCommitRequest request) { + this.groupTransferService.putRequest(request); + } + + + /** + * 判断主从之间数据传输是否正常 + * + * @return + */ + public boolean isSlaveOK(final long masterPutWhere) { + boolean result = this.connectionCount.get() > 0; + result = + result + && ((masterPutWhere - this.push2SlaveMaxOffset.get()) < this.defaultMessageStore + .getMessageStoreConfig().getHaSlaveFallbehindMax()); + return result; + } + + + /** + * 通知复制了部分数据 + */ + public void notifyTransferSome(final long offset) { + for (long value = this.push2SlaveMaxOffset.get(); offset > value;) { + boolean ok = this.push2SlaveMaxOffset.compareAndSet(value, offset); + if (ok) { + this.groupTransferService.notifyTransferSome(); + break; + } + else { + value = this.push2SlaveMaxOffset.get(); + } + } + } + + + public AtomicInteger getConnectionCount() { + return connectionCount; + } + + + // public void notifyTransferSome() { + // this.groupTransferService.notifyTransferSome(); + // } + + public void start() { + this.acceptSocketService.beginAccept(); + this.acceptSocketService.start(); + this.groupTransferService.start(); + this.haClient.start(); + } + + + public void addConnection(final HAConnection conn) { + synchronized (this.connectionList) { + this.connectionList.add(conn); + } + } + + + public void removeConnection(final HAConnection conn) { + synchronized (this.connectionList) { + this.connectionList.remove(conn); + } + } + + + public void shutdown() { + this.haClient.shutdown(); + this.acceptSocketService.shutdown(true); + this.destroyConnections(); + this.groupTransferService.shutdown(); + } + + + public void destroyConnections() { + synchronized (this.connectionList) { + for (HAConnection c : this.connectionList) { + c.shutdown(); + } + + this.connectionList.clear(); + } + } + + + public DefaultMessageStore getDefaultMessageStore() { + return defaultMessageStore; + } + + + public WaitNotifyObject getWaitNotifyObject() { + return waitNotifyObject; + } + class AcceptSocketService extends ServiceThread { private ServerSocketChannel serverSocketChannel; private Selector selector; @@ -112,9 +237,10 @@ public void run() { log.warn("Unexpected ops in select " + k.readyOps()); } } + + selected.clear(); } - selected.clear(); } catch (Exception e) { log.error(this.getServiceName() + " service has exception.", e); @@ -135,17 +261,10 @@ public String getServiceName() { * GroupTransferService Service */ class GroupTransferService extends ServiceThread { + // 异步通知 + private final WaitNotifyObject notifyTransferObject = new WaitNotifyObject(); private volatile List requestsWrite = new ArrayList(); private volatile List requestsRead = new ArrayList(); - // 첽֪ͨ - private final WaitNotifyObject notifyTransferObject = new WaitNotifyObject(); - - - private void swapRequests() { - List tmp = this.requestsWrite; - this.requestsWrite = this.requestsRead; - this.requestsRead = tmp; - } public void putRequest(final GroupCommitRequest request) { @@ -155,9 +274,9 @@ public void putRequest(final GroupCommitRequest request) { this.hasNotified = true; this.notify(); - // TODO ҪNotify߳ 1GroupTransferService - // 2WriteSocketService - // ڵputRequestѾNotifyWriteSocketService + // TODO 这里要Notify两个线程 1、GroupTransferService + // 2、WriteSocketService + // 在调用putRequest后,已经Notify了WriteSocketService } } } @@ -168,6 +287,13 @@ public void notifyTransferSome() { } + private void swapRequests() { + List tmp = this.requestsWrite; + this.requestsWrite = this.requestsRead; + this.requestsRead = tmp; + } + + private void doWaitTransfer() { if (!this.requestsRead.isEmpty()) { for (GroupCommitRequest req : this.requestsRead) { @@ -219,22 +345,18 @@ public String getServiceName() { } class HAClient extends ServiceThread { - // ڵIP:PORT + private static final int ReadMaxBufferSize = 1024 * 1024 * 4; + // 主节点IP:PORT private final AtomicReference masterAddress = new AtomicReference(); + // 向Master汇报Slave最大Offset + private final ByteBuffer reportOffset = ByteBuffer.allocate(8); private SocketChannel socketChannel; private Selector selector; - private long lastWriteTimestamp = System.currentTimeMillis(); - - // SlaveMaster㱨Offset㱨 + // Slave向Master汇报Offset,汇报到哪里 private long currentReportedOffset = 0; - - // Master㱨SlaveOffset - private final ByteBuffer reportOffset = ByteBuffer.allocate(8); - - private static final int ReadMaxBufferSize = 1024 * 1024 * 4; private int dispatchPostion = 0; - // MasterBuffer + // 从Master接收数据Buffer private ByteBuffer byteBufferRead = ByteBuffer.allocate(ReadMaxBufferSize); private ByteBuffer byteBufferBackup = ByteBuffer.allocate(ReadMaxBufferSize); @@ -254,9 +376,11 @@ public void updateMasterAddress(final String newAddr) { private boolean isTimeToReportOffset() { - long interval = HAService.this.defaultMessageStore.getSystemClock().now() - this.lastWriteTimestamp; + long interval = + HAService.this.defaultMessageStore.getSystemClock().now() - this.lastWriteTimestamp; boolean needHeart = - (interval > HAService.this.defaultMessageStore.getMessageStoreConfig().getHaSendHeartbeatInterval()); + (interval > HAService.this.defaultMessageStore.getMessageStoreConfig() + .getHaSendHeartbeatInterval()); return needHeart; } @@ -274,7 +398,8 @@ private boolean reportSlaveMaxOffset(final long maxOffset) { this.socketChannel.write(this.reportOffset); } catch (IOException e) { - log.error(this.getServiceName() + "reportSlaveMaxOffset this.socketChannel.write exception", e); + log.error(this.getServiceName() + + "reportSlaveMaxOffset this.socketChannel.write exception", e); return false; } } @@ -290,8 +415,9 @@ private boolean reportSlaveMaxOffset(final long maxOffset) { // this.dispatchPostion = 0; // this.byteBufferRead = bb; // } + /** - * BufferԺһ + * Buffer满了以后,重新整理一次 */ private void reallocateByteBuffer() { int remain = ReadMaxBufferSize - this.dispatchPostion; @@ -365,7 +491,7 @@ private boolean dispatchReadRequest() { long slavePhyOffset = HAService.this.defaultMessageStore.getMaxPhyOffset(); - // ش + // 发生重大错误 if (slavePhyOffset != 0) { if (slavePhyOffset != masterPhyOffset) { log.error("master pushed offset not equal the max phy offset in slave, SLAVE: " @@ -374,13 +500,13 @@ private boolean dispatchReadRequest() { } } - // Դչһ + // 可以凑够一个请求 if (diff >= (MSG_HEADER_SIZE + bodySize)) { byte[] bodyData = new byte[bodySize]; this.byteBufferRead.position(this.dispatchPostion + MSG_HEADER_SIZE); this.byteBufferRead.get(bodyData); - // TODO ǷҪʱ + // TODO 结果是否需要处理,暂时不处理 HAService.this.defaultMessageStore.appendToCommitLog(masterPhyOffset, bodyData); this.byteBufferRead.position(readSocketPos); @@ -407,7 +533,7 @@ private boolean dispatchReadRequest() { private boolean reportSlaveMaxOffsetPlus() { boolean result = true; - // ֻҪи£ͻ㱨Offset + // 只要本地有更新,就汇报最大物理Offset long currentPhyOffset = HAService.this.defaultMessageStore.getMaxPhyOffset(); if (currentPhyOffset > this.currentReportedOffset) { this.currentReportedOffset = currentPhyOffset; @@ -422,61 +548,6 @@ private boolean reportSlaveMaxOffsetPlus() { } - @Override - public void run() { - log.info(this.getServiceName() + " service started"); - - while (!this.isStoped()) { - try { - if (this.connectMaster()) { - // Ȼ㱨Offset || ʱʽ㱨 - if (this.isTimeToReportOffset()) { - boolean result = this.reportSlaveMaxOffset(this.currentReportedOffset); - if (!result) { - this.closeMaster(); - } - } - - // ȴӦ - this.selector.select(1000); - - // - boolean ok = this.processReadEvent(); - if (!ok) { - this.closeMaster(); - } - - // ֻҪи£ͻ㱨Offset - if (!reportSlaveMaxOffsetPlus()) { - continue; - } - - // Masterķ - long interval = - HAService.this.getDefaultMessageStore().getSystemClock().now() - - this.lastWriteTimestamp; - if (interval > HAService.this.getDefaultMessageStore().getMessageStoreConfig() - .getHaHousekeepingInterval()) { - log.warn("HAClient, housekeeping, found this connection[" + this.masterAddress - + "] expired, " + interval); - this.closeMaster(); - log.warn("HAClient, master not response some time, so close connection"); - } - } - else { - this.waitForRunning(1000 * 5); - } - } - catch (Exception e) { - log.warn(this.getServiceName() + " service has exception. ", e); - this.waitForRunning(1000 * 5); - } - } - - log.info(this.getServiceName() + " service end"); - } - - private boolean connectMaster() throws ClosedChannelException { if (null == socketChannel) { String addr = this.masterAddress.get(); @@ -491,7 +562,7 @@ private boolean connectMaster() throws ClosedChannelException { } } - // ÿʱҪõOffset + // 每次连接时,要重新拿到最大的Offset this.currentReportedOffset = HAService.this.defaultMessageStore.getMaxPhyOffset(); this.lastWriteTimestamp = System.currentTimeMillis(); @@ -530,6 +601,61 @@ private void closeMaster() { } + @Override + public void run() { + log.info(this.getServiceName() + " service started"); + + while (!this.isStoped()) { + try { + if (this.connectMaster()) { + // 先汇报最大物理Offset || 定时心跳方式汇报 + if (this.isTimeToReportOffset()) { + boolean result = this.reportSlaveMaxOffset(this.currentReportedOffset); + if (!result) { + this.closeMaster(); + } + } + + // 等待应答 + this.selector.select(1000); + + // 接收数据 + boolean ok = this.processReadEvent(); + if (!ok) { + this.closeMaster(); + } + + // 只要本地有更新,就汇报最大物理Offset + if (!reportSlaveMaxOffsetPlus()) { + continue; + } + + // 检查Master的反向心跳 + long interval = + HAService.this.getDefaultMessageStore().getSystemClock().now() + - this.lastWriteTimestamp; + if (interval > HAService.this.getDefaultMessageStore().getMessageStoreConfig() + .getHaHousekeepingInterval()) { + log.warn("HAClient, housekeeping, found this connection[" + this.masterAddress + + "] expired, " + interval); + this.closeMaster(); + log.warn("HAClient, master not response some time, so close connection"); + } + } + else { + this.waitForRunning(1000 * 5); + } + } + catch (Exception e) { + log.warn(this.getServiceName() + " service has exception. ", e); + this.waitForRunning(1000 * 5); + } + } + + log.info(this.getServiceName() + " service end"); + } + + // // private void disableWriteFlag() { // if (this.socketChannel != null) { @@ -559,117 +685,4 @@ public String getServiceName() { return HAClient.class.getSimpleName(); } } - - - public HAService(final DefaultMessageStore defaultMessageStore) throws IOException { - this.defaultMessageStore = defaultMessageStore; - this.acceptSocketService = - new AcceptSocketService(defaultMessageStore.getMessageStoreConfig().getHaListenPort()); - this.groupTransferService = new GroupTransferService(); - this.haClient = new HAClient(); - } - - - public void updateMasterAddress(final String newAddr) { - if (this.haClient != null) { - this.haClient.updateMasterAddress(newAddr); - } - } - - - public void putRequest(final GroupCommitRequest request) { - this.groupTransferService.putRequest(request); - } - - - // public void notifyTransferSome() { - // this.groupTransferService.notifyTransferSome(); - // } - - /** - * ж֮ݴǷ - * - * @return - */ - public boolean isSlaveOK(final long masterPutWhere) { - boolean result = this.connectionCount.get() > 0; - result = - result - && ((masterPutWhere - this.push2SlaveMaxOffset.get()) < this.defaultMessageStore - .getMessageStoreConfig().getHaSlaveFallbehindMax()); - return result; - } - - - /** - * ֪ͨ˲ - */ - public void notifyTransferSome(final long offset) { - for (long value = this.push2SlaveMaxOffset.get(); offset > value;) { - boolean ok = this.push2SlaveMaxOffset.compareAndSet(value, offset); - if (ok) { - this.groupTransferService.notifyTransferSome(); - break; - } - else { - value = this.push2SlaveMaxOffset.get(); - } - } - } - - - public AtomicInteger getConnectionCount() { - return connectionCount; - } - - - public void start() { - this.acceptSocketService.beginAccept(); - this.acceptSocketService.start(); - this.groupTransferService.start(); - this.haClient.start(); - } - - - public void destroyConnections() { - synchronized (this.connectionList) { - for (HAConnection c : this.connectionList) { - c.shutdown(); - } - - this.connectionList.clear(); - } - } - - - public void addConnection(final HAConnection conn) { - synchronized (this.connectionList) { - this.connectionList.add(conn); - } - } - - - public void removeConnection(final HAConnection conn) { - synchronized (this.connectionList) { - this.connectionList.remove(conn); - } - } - - - public void shutdown() { - this.haClient.shutdown(); - this.acceptSocketService.shutdown(true); - this.destroyConnections(); - this.groupTransferService.shutdown(); - } - - - public DefaultMessageStore getDefaultMessageStore() { - return defaultMessageStore; - } - - - public WaitNotifyObject getWaitNotifyObject() { - return waitNotifyObject; - } } diff --git a/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/ha/WaitNotifyObject.java b/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/ha/WaitNotifyObject.java index 70992e63..277853a3 100644 --- a/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/ha/WaitNotifyObject.java +++ b/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/ha/WaitNotifyObject.java @@ -1,5 +1,17 @@ /** - * $Id: WaitNotifyObject.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.store.ha; @@ -7,16 +19,17 @@ /** - * ֮߳첽֪ͨ + * 用来做线程之间异步通知 * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * @author shijia.wxr + * @since 2013-7-21 */ public class WaitNotifyObject { - // ǷѾNotify - protected volatile boolean hasNotified = false; - // ǷѾNotify㲥ģʽ + // 是否已经被Notify过,广播模式 protected final HashMap waitingThreadTable = new HashMap(16); + // 是否已经被Notify过 + protected volatile boolean hasNotified = false; public void wakeup() { @@ -51,8 +64,12 @@ protected void waitForRunning(long interval) { } + protected void onWaitEnd() { + } + + /** - * 㲥ʽ + * 广播方式唤醒 */ public void wakeupAll() { synchronized (this) { @@ -71,7 +88,7 @@ public void wakeupAll() { /** - * ̵߳wait + * 多个线程调用wait */ public void allWaitForRunning(long interval) { long currentThreadId = Thread.currentThread().getId(); @@ -95,8 +112,4 @@ public void allWaitForRunning(long interval) { } } } - - - protected void onWaitEnd() { - } } diff --git a/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/index/IndexFile.java b/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/index/IndexFile.java index 654d4e93..c99a6a96 100644 --- a/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/index/IndexFile.java +++ b/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/index/IndexFile.java @@ -1,5 +1,17 @@ /** - * $Id: IndexFile.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.store.index; @@ -13,22 +25,21 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.alibaba.rocketmq.common.MixAll; +import com.alibaba.rocketmq.common.constant.LoggerName; import com.alibaba.rocketmq.store.MapedFile; /** - * 洢ϢϢļ + * 存储具体消息索引信息的文件 * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * @author shijia.wxr + * @since 2013-7-21 */ public class IndexFile { - private static final Logger log = LoggerFactory.getLogger(MixAll.StoreLoggerName); - + private static final Logger log = LoggerFactory.getLogger(LoggerName.StoreLoggerName); private static int HASH_SLOT_SIZE = 4; private static int INDEX_SIZE = 20; private static int INVALID_INDEX = 0; - private final int hashSlotNum; private final int indexNum; private final MapedFile mapedFile; @@ -37,8 +48,8 @@ public class IndexFile { private final IndexHeader indexHeader; - public IndexFile(final String fileName, final int hashSlotNum, final int indexNum, final long endPhyOffset, - final long endTimestamp) throws IOException { + public IndexFile(final String fileName, final int hashSlotNum, final int indexNum, + final long endPhyOffset, final long endTimestamp) throws IOException { int fileTotalSize = IndexHeader.INDEX_HEADER_SIZE + (hashSlotNum * HASH_SLOT_SIZE) + (indexNum * INDEX_SIZE); this.mapedFile = new MapedFile(fileName, fileTotalSize); @@ -84,7 +95,7 @@ public void flush() { /** - * ǰļǷд + * 当前索引文件是否写满 */ public boolean isWriteFull() { return this.indexHeader.getIndexCount() >= this.indexNum; @@ -97,18 +108,21 @@ public boolean destroy(final long intervalForcibly) { /** - * falseʾҪµļ + * 如果返回false,表示需要创建新的索引文件 */ public boolean putKey(final String key, final long phyOffset, final long storeTimestamp) { if (this.indexHeader.getIndexCount() < this.indexNum) { int keyHash = key.hashCode(); + // Math.abs计算结果依旧为负 + if (Integer.MIN_VALUE == keyHash) + keyHash = 0; int slotPos = Math.abs(keyHash) % this.hashSlotNum; int absSlotPos = IndexHeader.INDEX_HEADER_SIZE + slotPos * HASH_SLOT_SIZE; FileLock fileLock = null; try { - // TODO ǷǶд + // TODO 是否是读写锁 fileLock = this.fileChannel.lock(absSlotPos, HASH_SLOT_SIZE, false); int slotValue = this.mappedByteBuffer.getInt(absSlotPos); if (slotValue <= INVALID_INDEX || slotValue > this.indexHeader.getIndexCount()) { @@ -126,20 +140,23 @@ else if (timeDiff < 0) { timeDiff = 0; } + // 时间差存储单位由毫秒改为秒 + timeDiff = timeDiff / 1000; + int absIndexPos = IndexHeader.INDEX_HEADER_SIZE + this.hashSlotNum * HASH_SLOT_SIZE + this.indexHeader.getIndexCount() * INDEX_SIZE; - // д + // 写入真正索引 this.mappedByteBuffer.putInt(absIndexPos, keyHash); this.mappedByteBuffer.putLong(absIndexPos + 4, phyOffset); this.mappedByteBuffer.putInt(absIndexPos + 4 + 8, (int) timeDiff); this.mappedByteBuffer.putInt(absIndexPos + 4 + 8 + 4, slotValue); - // ¹ϣ + // 更新哈希槽 this.mappedByteBuffer.putInt(absSlotPos, this.indexHeader.getIndexCount()); - // һд + // 第一次写入 if (this.indexHeader.getIndexCount() <= 1) { this.indexHeader.setBeginPhyOffset(phyOffset); this.indexHeader.setBeginTimestamp(storeTimestamp); @@ -153,7 +170,7 @@ else if (timeDiff < 0) { return true; } catch (Exception e) { - log.error("putKey exception ", e); + log.error("putKey exception, Key: " + key + " KeyHashCode: " + key.hashCode(), e); } finally { if (fileLock != null) { @@ -167,7 +184,8 @@ else if (timeDiff < 0) { } } else { - log.warn("putKey index count " + this.indexHeader.getIndexCount() + " index max num " + this.indexNum); + log.warn("putKey index count " + this.indexHeader.getIndexCount() + " index max num " + + this.indexNum); } return false; @@ -190,10 +208,11 @@ public long getEndPhyOffset() { /** - * ʱǷƥ + * 时间区间是否匹配 */ public boolean isTimeMatched(final long begin, final long end) { - boolean result = begin < this.indexHeader.getBeginTimestamp() && end > this.indexHeader.getEndTimestamp(); + boolean result = + begin < this.indexHeader.getBeginTimestamp() && end > this.indexHeader.getEndTimestamp(); result = result @@ -209,12 +228,14 @@ public boolean isTimeMatched(final long begin, final long end) { /** - * ǰ᣺ʱڵǰѾƥ˵ǰļʼʱ + * 前提:入参时间区间在调用前已经匹配了当前索引文件的起始结束时间 */ - public void selectPhyOffset(final List phyOffsets, final String key, final int maxNum, final long begin, - final long end, boolean lock) { + public void selectPhyOffset(final List phyOffsets, final String key, final int maxNum, + final long begin, final long end, boolean lock) { if (this.mapedFile.hold()) { int keyHash = key.hashCode(); + if (Integer.MIN_VALUE == keyHash) + keyHash = 0; int slotPos = Math.abs(keyHash) % this.hashSlotNum; int absSlotPos = IndexHeader.INDEX_HEADER_SIZE + slotPos * HASH_SLOT_SIZE; @@ -249,11 +270,14 @@ public void selectPhyOffset(final List phyOffsets, final String key, final int timeDiff = this.mappedByteBuffer.getInt(absIndexPos + 4 + 8); int prevIndexRead = this.mappedByteBuffer.getInt(absIndexPos + 4 + 8 + 4); - // δ֪ + // 读到了未知数据 if (timeDiff < 0) { break; } + // 时间差存储的是秒,再还原为毫秒 + timeDiff *= 1000; + long timeRead = this.indexHeader.getBeginTimestamp() + timeDiff; boolean timeMatched = (timeRead >= begin) && (timeRead <= end); @@ -261,7 +285,8 @@ public void selectPhyOffset(final List phyOffsets, final String key, final phyOffsets.add(phyOffsetRead); } - if (prevIndexRead <= INVALID_INDEX || prevIndexRead > this.indexHeader.getIndexCount() + if (prevIndexRead <= INVALID_INDEX + || prevIndexRead > this.indexHeader.getIndexCount() || prevIndexRead == nextIndexToRead || timeRead < begin) { break; } diff --git a/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/index/IndexHeader.java b/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/index/IndexHeader.java index 3475d11f..909d9446 100644 --- a/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/index/IndexHeader.java +++ b/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/index/IndexHeader.java @@ -1,5 +1,17 @@ /** - * $Id: IndexHeader.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.store.index; @@ -9,29 +21,27 @@ /** - * ļͷ + * 索引文件头 * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * @author shijia.wxr + * @since 2013-7-21 */ public class IndexHeader { public static final int INDEX_HEADER_SIZE = 40; - - private AtomicLong beginTimestamp = new AtomicLong(0); - private AtomicLong endTimestamp = new AtomicLong(0); - private AtomicLong beginPhyOffset = new AtomicLong(0); - private AtomicLong endPhyOffset = new AtomicLong(0); - private AtomicInteger hashSlotCount = new AtomicInteger(0); - // һЧ - private AtomicInteger indexCount = new AtomicInteger(1); - private static int BEGINTIMESTAMP_INDEX = 0; private static int ENDTIMESTAMP_INDEX = 8; private static int BEGINPHYOFFSET_INDEX = 16; private static int ENDPHYOFFSET_INDEX = 24; private static int HASHSLOTCOUNT_INDEX = 32; private static int INDEXCOUNT_INDEX = 36; - private final ByteBuffer byteBuffer; + private AtomicLong beginTimestamp = new AtomicLong(0); + private AtomicLong endTimestamp = new AtomicLong(0); + private AtomicLong beginPhyOffset = new AtomicLong(0); + private AtomicLong endPhyOffset = new AtomicLong(0); + private AtomicInteger hashSlotCount = new AtomicInteger(0); + // 第一个索引是无效索引 + private AtomicInteger indexCount = new AtomicInteger(1); public IndexHeader(final ByteBuffer byteBuffer) { @@ -55,7 +65,7 @@ public void load() { /** - * byteBuffer + * 更新byteBuffer */ public void updateByteBuffer() { this.byteBuffer.putLong(BEGINTIMESTAMP_INDEX, this.beginTimestamp.get()); diff --git a/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/index/IndexService.java b/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/index/IndexService.java index 2001cb11..1720e99f 100644 --- a/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/index/IndexService.java +++ b/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/index/IndexService.java @@ -1,5 +1,17 @@ /** - * $Id: IndexService.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.store.index; @@ -10,44 +22,39 @@ import java.util.List; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.alibaba.rocketmq.common.Message; -import com.alibaba.rocketmq.common.UtilALl; -import com.alibaba.rocketmq.common.MixAll; import com.alibaba.rocketmq.common.ServiceThread; +import com.alibaba.rocketmq.common.UtilAll; +import com.alibaba.rocketmq.common.constant.LoggerName; +import com.alibaba.rocketmq.common.message.MessageConst; import com.alibaba.rocketmq.common.sysflag.MessageSysFlag; import com.alibaba.rocketmq.store.DefaultMessageStore; import com.alibaba.rocketmq.store.DispatchRequest; /** - * Ϣ + * 消息索引服务 * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * @author shijia.wxr + * @since 2013-7-21 */ public class IndexService extends ServiceThread { - private static final Logger log = LoggerFactory.getLogger(MixAll.StoreLoggerName); - - private LinkedBlockingQueue requestQueue = new LinkedBlockingQueue(); - private AtomicInteger requestCount = new AtomicInteger(0); - + private static final Logger log = LoggerFactory.getLogger(LoggerName.StoreLoggerName); private final DefaultMessageStore defaultMessageStore; - - // + // 索引配置 private final int hashSlotNum; private final int indexNum; private final String storePath; - - // ļ + // 索引文件集合 private final ArrayList indexFileList = new ArrayList(); - // дindexFileList + // 读写锁(针对indexFileList) private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock(); + private LinkedBlockingQueue requestQueue = new LinkedBlockingQueue(300000); public IndexService(final DefaultMessageStore store) { @@ -92,93 +99,7 @@ public boolean load(final boolean lastExitOK) { /** - * ȡһļΪջһļдˣ½һļ
- * ֻһ̵߳ãԲд - */ - public IndexFile getAndCreateLastIndexFile() { - IndexFile indexFile = null; - long lastUpdateEndPhyOffset = 0; - long lastUpdateIndexTimestamp = 0; - // ȳʹö - { - this.readWriteLock.readLock().lock(); - if (!this.indexFileList.isEmpty()) { - IndexFile tmp = this.indexFileList.get(this.indexFileList.size() - 1); - if (!tmp.isWriteFull()) { - indexFile = tmp; - } - else { - lastUpdateEndPhyOffset = tmp.getEndPhyOffset(); - lastUpdateIndexTimestamp = tmp.getEndTimestamp(); - } - } - - this.readWriteLock.readLock().unlock(); - } - - // ûҵʹдļ - if (indexFile == null) { - try { - String fileName = - this.storePath + File.separator - + UtilALl.timeMillisToHumanString(System.currentTimeMillis()); - indexFile = - new IndexFile(fileName, this.hashSlotNum, this.indexNum, lastUpdateEndPhyOffset, - lastUpdateIndexTimestamp); - this.readWriteLock.writeLock().lock(); - this.indexFileList.add(indexFile); - } - catch (Exception e) { - log.error("getLastIndexFile exception ", e); - } - finally { - this.readWriteLock.writeLock().unlock(); - } - - // ÿһļˢһ - if (indexFile != null) { - Thread flushThread = new Thread(new Runnable() { - @Override - public void run() { - IndexService.this.flush(); - } - }, "FlushIndexFileThread"); - - flushThread.setDaemon(true); - flushThread.start(); - } - } - - return indexFile; - } - - - /** - * ɾļֻܴͷʼɾ - */ - private void deleteExpiredFile(List files) { - if (!files.isEmpty()) { - try { - this.readWriteLock.writeLock().lock(); - for (IndexFile file : files) { - if (!this.indexFileList.remove(file)) { - log.error("deleteExpiredFile remove failed."); - break; - } - } - } - catch (Exception e) { - log.error("deleteExpiredFile has exception.", e); - } - finally { - this.readWriteLock.writeLock().unlock(); - } - } - } - - - /** - * ɾļ + * 删除索引文件 */ public void deleteExpiredFile(long offset) { Object[] files = null; @@ -217,6 +138,32 @@ public void deleteExpiredFile(long offset) { } + /** + * 删除文件只能从头开始删 + */ + private void deleteExpiredFile(List files) { + if (!files.isEmpty()) { + try { + this.readWriteLock.writeLock().lock(); + for (IndexFile file : files) { + boolean destroyed = file.destroy(3000); + destroyed = destroyed && this.indexFileList.remove(file); + if (!destroyed) { + log.error("deleteExpiredFile remove failed."); + break; + } + } + } + catch (Exception e) { + log.error("deleteExpiredFile has exception.", e); + } + finally { + this.readWriteLock.writeLock().unlock(); + } + } + } + + public void destroy() { try { this.readWriteLock.readLock().lock(); @@ -234,39 +181,9 @@ public void destroy() { } - public void flush() { - ArrayList indexFileListClone = null; - try { - this.readWriteLock.readLock().lock(); - indexFileListClone = (ArrayList) this.indexFileList.clone(); - } - catch (Exception e) { - log.error("flush exception", e); - } - finally { - this.readWriteLock.readLock().unlock(); - } - - long indexMsgTimestamp = 0; - - if (indexFileListClone != null) { - for (IndexFile f : indexFileListClone) { - if (f.isWriteFull()) { - indexMsgTimestamp = f.getEndTimestamp(); - } - - f.flush(); - } - } - - this.defaultMessageStore.getStoreCheckpoint().setIndexMsgTimestamp(indexMsgTimestamp); - this.defaultMessageStore.getStoreCheckpoint().flush(); - } - - public QueryOffsetResult queryOffset(String topic, String key, int maxNum, long begin, long end) { List phyOffsets = new ArrayList(maxNum); - // TODO Ҫظû + // TODO 可能需要返回给最终用户 long indexLastUpdateTimestamp = 0; long indexLastUpdatePhyoffset = 0; maxNum = Math.min(maxNum, this.defaultMessageStore.getMessageStoreConfig().getMaxMsgsNumBatch()); @@ -282,11 +199,11 @@ public QueryOffsetResult queryOffset(String topic, String key, int maxNum, long } if (f.isTimeMatched(begin, end)) { - // һļҪ + // 最后一个文件需要加锁 f.selectPhyOffset(phyOffsets, this.buildKey(topic, key), maxNum, begin, end, lastFile); } - // ǰʱ + // 再往前遍历时间更不符合 if (f.getBeginTimestamp() > end) { break; } @@ -308,45 +225,42 @@ public QueryOffsetResult queryOffset(String topic, String key, int maxNum, long } - /** - * ׷󣬷ضжѻ - */ - public int putRequest(final Object[] reqs) { - this.requestQueue.add(reqs); - return this.requestCount.addAndGet(reqs.length); - } - - private String buildKey(final String topic, final String key) { return topic + "#" + key; } - public IndexFile retryGetAndCreateIndexFile() { - IndexFile indexFile = null; + /** + * 向队列中添加请求,队列满情况下,丢弃请求 + */ + public void putRequest(final Object[] reqs) { + boolean offer = this.requestQueue.offer(reqs); + if (!offer) { + if (log.isDebugEnabled()) { + log.debug("putRequest index failed, {}", reqs); + } + } + } - // ʧܣؽ3 - for (int times = 0; null == indexFile && times < 3; times++) { - indexFile = this.getAndCreateLastIndexFile(); - if (null != indexFile) - break; + @Override + public void run() { + log.info(this.getServiceName() + " service started"); + + while (!this.isStoped()) { try { - log.error("try to create index file, " + times + " times"); - Thread.sleep(1000); + Object[] req = this.requestQueue.poll(3000, TimeUnit.MILLISECONDS); + + if (req != null) { + this.buildIndex(req); + } } - catch (InterruptedException e) { - e.printStackTrace(); + catch (Exception e) { + log.warn(this.getServiceName() + " service has exception. ", e); } } - // ԶΣȻ޷ļ - if (null == indexFile) { - this.defaultMessageStore.getAccessRights().makeIndexFileError(); - log.error("mark index file can not build flag"); - } - - return indexFile; + log.info(this.getServiceName() + " service end"); } @@ -374,9 +288,9 @@ public void buildIndex(Object[] req) { } if (keys != null && keys.length() > 0) { - String[] keyset = keys.split(Message.KEY_SEPARATOR); + String[] keyset = keys.split(MessageConst.KEY_SEPARATOR); for (String key : keyset) { - // TODO ǷҪTRIM + // TODO 是否需要TRIM if (key.length() > 0) { for (boolean ok = indexFile.putKey(buildKey(topic, key), msg.getCommitLogOffset(), @@ -397,39 +311,126 @@ public void buildIndex(Object[] req) { } } } - // IOϣbuildжϣҪ˹봦 + // IO发生故障,build索引过程中断,需要人工参与处理 else { breakdown = true; } if (breakdown) { log.error("build index error, stop building index"); - // TODO } - - this.requestCount.addAndGet(req.length * (-1)); } - @Override - public void run() { - log.info(this.getServiceName() + " service started"); + public IndexFile retryGetAndCreateIndexFile() { + IndexFile indexFile = null; + + // 如果创建失败,尝试重建3次 + for (int times = 0; null == indexFile && times < 3; times++) { + indexFile = this.getAndCreateLastIndexFile(); + if (null != indexFile) + break; - while (!this.isStoped()) { try { - // Object[] req = this.requestQueue.take(); - Object[] req = this.requestQueue.poll(3000, TimeUnit.MILLISECONDS); + log.error("try to create index file, " + times + " times"); + Thread.sleep(1000); + } + catch (InterruptedException e) { + e.printStackTrace(); + } + } - if (req != null) { - this.buildIndex(req); + // 重试多次,仍然无法创建索引文件 + if (null == indexFile) { + this.defaultMessageStore.getAccessRights().makeIndexFileError(); + log.error("mark index file can not build flag"); + } + + return indexFile; + } + + + /** + * 获取最后一个索引文件,如果集合为空或者最后一个文件写满了,则新建一个文件
+ * 只有一个线程调用,所以不存在写竟争问题 + */ + public IndexFile getAndCreateLastIndexFile() { + IndexFile indexFile = null; + IndexFile prevIndexFile = null; + long lastUpdateEndPhyOffset = 0; + long lastUpdateIndexTimestamp = 0; + // 先尝试使用读锁 + { + this.readWriteLock.readLock().lock(); + if (!this.indexFileList.isEmpty()) { + IndexFile tmp = this.indexFileList.get(this.indexFileList.size() - 1); + if (!tmp.isWriteFull()) { + indexFile = tmp; } + else { + lastUpdateEndPhyOffset = tmp.getEndPhyOffset(); + lastUpdateIndexTimestamp = tmp.getEndTimestamp(); + prevIndexFile = tmp; + } + } + + this.readWriteLock.readLock().unlock(); + } + + // 如果没找到,使用写锁创建文件 + if (indexFile == null) { + try { + String fileName = + this.storePath + File.separator + + UtilAll.timeMillisToHumanString(System.currentTimeMillis()); + indexFile = + new IndexFile(fileName, this.hashSlotNum, this.indexNum, lastUpdateEndPhyOffset, + lastUpdateIndexTimestamp); + this.readWriteLock.writeLock().lock(); + this.indexFileList.add(indexFile); } catch (Exception e) { - log.warn(this.getServiceName() + " service has exception. ", e); + log.error("getLastIndexFile exception ", e); + } + finally { + this.readWriteLock.writeLock().unlock(); + } + + // 每创建一个新文件,之前文件要刷盘 + if (indexFile != null) { + final IndexFile flushThisFile = prevIndexFile; + Thread flushThread = new Thread(new Runnable() { + @Override + public void run() { + IndexService.this.flush(flushThisFile); + } + }, "FlushIndexFileThread"); + + flushThread.setDaemon(true); + flushThread.start(); } } - log.info(this.getServiceName() + " service end"); + return indexFile; + } + + + public void flush(final IndexFile f) { + if (null == f) + return; + + long indexMsgTimestamp = 0; + + if (f.isWriteFull()) { + indexMsgTimestamp = f.getEndTimestamp(); + } + + f.flush(); + + if (indexMsgTimestamp > 0) { + this.defaultMessageStore.getStoreCheckpoint().setIndexMsgTimestamp(indexMsgTimestamp); + this.defaultMessageStore.getStoreCheckpoint().flush(); + } } diff --git a/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/index/QueryOffsetResult.java b/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/index/QueryOffsetResult.java index 03948030..30246ebe 100644 --- a/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/index/QueryOffsetResult.java +++ b/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/index/QueryOffsetResult.java @@ -1,5 +1,17 @@ /** - * $Id: QueryOffsetResult.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.store.index; @@ -7,9 +19,10 @@ /** - * ѯϢؽ + * 根据索引查询消息,返回结果 * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * @author shijia.wxr + * @since 2013-7-21 */ public class QueryOffsetResult { private final List phyOffsets; @@ -17,7 +30,8 @@ public class QueryOffsetResult { private final long indexLastUpdatePhyoffset; - public QueryOffsetResult(List phyOffsets, long indexLastUpdateTimestamp, long indexLastUpdatePhyoffset) { + public QueryOffsetResult(List phyOffsets, long indexLastUpdateTimestamp, + long indexLastUpdatePhyoffset) { this.phyOffsets = phyOffsets; this.indexLastUpdateTimestamp = indexLastUpdateTimestamp; this.indexLastUpdatePhyoffset = indexLastUpdatePhyoffset; diff --git a/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/schedule/DelayOffsetSerializeWrapper.java b/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/schedule/DelayOffsetSerializeWrapper.java new file mode 100644 index 00000000..3835648c --- /dev/null +++ b/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/schedule/DelayOffsetSerializeWrapper.java @@ -0,0 +1,42 @@ +/** + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.rocketmq.store.schedule; + +import java.util.concurrent.ConcurrentHashMap; + +import com.alibaba.rocketmq.remoting.protocol.RemotingSerializable; + + +/** + * 延时消息进度,序列化包装 + * + * @author shijia.wxr + * @since 2013-7-21 + */ +public class DelayOffsetSerializeWrapper extends RemotingSerializable { + private ConcurrentHashMap offsetTable = + new ConcurrentHashMap(32); + + + public ConcurrentHashMap getOffsetTable() { + return offsetTable; + } + + + public void setOffsetTable(ConcurrentHashMap offsetTable) { + this.offsetTable = offsetTable; + } +} diff --git a/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/schedule/ScheduleMessageService.java b/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/schedule/ScheduleMessageService.java index 52996b55..20e26b36 100644 --- a/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/schedule/ScheduleMessageService.java +++ b/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/schedule/ScheduleMessageService.java @@ -1,25 +1,37 @@ /** - * $Id: ScheduleMessageService.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.store.schedule; import java.util.HashMap; -import java.util.Properties; -import java.util.Set; +import java.util.Iterator; +import java.util.Map.Entry; import java.util.Timer; import java.util.TimerTask; import java.util.concurrent.ConcurrentHashMap; -import org.apache.commons.io.IOUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.alibaba.rocketmq.common.Message; -import com.alibaba.rocketmq.common.MessageDecoder; -import com.alibaba.rocketmq.common.MessageExt; -import com.alibaba.rocketmq.common.MixAll; +import com.alibaba.rocketmq.common.ConfigManager; import com.alibaba.rocketmq.common.TopicFilterType; -import com.alibaba.rocketmq.common.sysflag.MessageSysFlag; +import com.alibaba.rocketmq.common.constant.LoggerName; +import com.alibaba.rocketmq.common.message.MessageConst; +import com.alibaba.rocketmq.common.message.MessageDecoder; +import com.alibaba.rocketmq.common.message.MessageExt; +import com.alibaba.rocketmq.common.running.RunningStats; import com.alibaba.rocketmq.store.ConsumeQueue; import com.alibaba.rocketmq.store.DefaultMessageStore; import com.alibaba.rocketmq.store.MessageExtBrokerInner; @@ -29,34 +41,184 @@ /** - * ʱϢ - * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * 定时消息服务 * + * @author shijia.wxr + * @since 2013-7-21 */ -public class ScheduleMessageService { - private static final Logger log = LoggerFactory.getLogger(MixAll.StoreLoggerName); +public class ScheduleMessageService extends ConfigManager { public static final String SCHEDULE_TOPIC = "SCHEDULE_TOPIC_XXXX"; + private static final Logger log = LoggerFactory.getLogger(LoggerName.StoreLoggerName); private static final long FIRST_DELAY_TIME = 1000L; private static final long DELAY_FOR_A_WHILE = 100L; private static final long DELAY_FOR_A_PERIOD = 10000L; - - // ÿlevelӦʱʱ + // 每个level对应的延时时间 private final ConcurrentHashMap delayLevelTable = new ConcurrentHashMap(32); - - // ʱ㵽 + // 延时计算到了哪里 private final ConcurrentHashMap offsetTable = new ConcurrentHashMap(32); - - // ֵ + // 定时器 + private final Timer timer = new Timer("ScheduleMessageTimerThread", true); + // 存储顶层对象 + private final DefaultMessageStore defaultMessageStore; + // 最大值 private int maxDelayLevel; - // ʱ - private final Timer timer = new Timer("ScheduleMessageTimerThread", true); - // 洢 - private final DefaultMessageStore defaultMessageStore; + public ScheduleMessageService(final DefaultMessageStore defaultMessageStore) { + this.defaultMessageStore = defaultMessageStore; + } + + + public void buildRunningStats(HashMap stats) { + Iterator> it = this.offsetTable.entrySet().iterator(); + while (it.hasNext()) { + Entry next = it.next(); + int queueId = delayLevel2QueueId(next.getKey()); + long delayOffset = next.getValue(); + long maxOffset = this.defaultMessageStore.getMaxOffsetInQuque(SCHEDULE_TOPIC, queueId); + String value = String.format("%d,%d", delayOffset, maxOffset); + String key = String.format("%s_%d", RunningStats.scheduleMessageOffset.name(), next.getKey()); + stats.put(key, value); + } + } + + + public static int queueId2DelayLevel(final int queueId) { + return queueId + 1; + } + + + public static int delayLevel2QueueId(final int delayLevel) { + return delayLevel - 1; + } + + + private void updateOffset(int delayLevel, long offset) { + this.offsetTable.put(delayLevel, offset); + } + + + public long computeDeliverTimestamp(final int delayLevel, final long storeTimestamp) { + Long time = this.delayLevelTable.get(delayLevel); + if (time != null) { + return time + storeTimestamp; + } + + return storeTimestamp + 1000; + } + + + public void start() { + // 为每个延时队列增加定时器 + for (Integer level : this.delayLevelTable.keySet()) { + Long timeDelay = this.delayLevelTable.get(level); + Long offset = this.offsetTable.get(level); + if (null == offset) { + offset = 0L; + } + + if (timeDelay != null) { + this.timer.schedule(new DeliverDelayedMessageTimerTask(level, offset), FIRST_DELAY_TIME); + } + } + + // 定时将延时进度刷盘 + this.timer.scheduleAtFixedRate(new TimerTask() { + + @Override + public void run() { + try { + ScheduleMessageService.this.persist(); + } + catch (Exception e) { + log.error("scheduleAtFixedRate flush exception", e); + } + } + }, 10000, this.defaultMessageStore.getMessageStoreConfig().getFlushDelayOffsetInterval()); + } + + + public void shutdown() { + this.timer.cancel(); + } + + + public int getMaxDelayLevel() { + return maxDelayLevel; + } + + + public String encode() { + return this.encode(false); + } + + + public String encode(final boolean prettyFormat) { + DelayOffsetSerializeWrapper delayOffsetSerializeWrapper = new DelayOffsetSerializeWrapper(); + delayOffsetSerializeWrapper.setOffsetTable(this.offsetTable); + return delayOffsetSerializeWrapper.toJson(prettyFormat); + } + + + @Override + public void decode(String jsonString) { + if (jsonString != null) { + DelayOffsetSerializeWrapper delayOffsetSerializeWrapper = + DelayOffsetSerializeWrapper.fromJson(jsonString, DelayOffsetSerializeWrapper.class); + if (delayOffsetSerializeWrapper != null) { + this.offsetTable.putAll(delayOffsetSerializeWrapper.getOffsetTable()); + } + } + } + + + @Override + public String configFilePath() { + return this.defaultMessageStore.getMessageStoreConfig().getDelayOffsetStorePath(); + } + + + public boolean load() { + boolean result = super.load(); + result = result && this.parseDelayLevel(); + return result; + } + + + public boolean parseDelayLevel() { + HashMap timeUnitTable = new HashMap(); + timeUnitTable.put("s", 1000L); + timeUnitTable.put("m", 1000L * 60); + timeUnitTable.put("h", 1000L * 60 * 60); + timeUnitTable.put("d", 1000L * 60 * 60 * 24); + + String levelString = this.defaultMessageStore.getMessageStoreConfig().getMessageDelayLevel(); + try { + String[] levelArray = levelString.split(" "); + for (int i = 0; i < levelArray.length; i++) { + String value = levelArray[i]; + String ch = value.substring(value.length() - 1); + Long tu = timeUnitTable.get(ch); + + int level = i + 1; + if (level > this.maxDelayLevel) { + this.maxDelayLevel = level; + } + long num = Long.parseLong(value.substring(0, value.length() - 1)); + long delayTimeMillis = tu * num; + this.delayLevelTable.put(level, delayTimeMillis); + } + } + catch (Exception e) { + log.error("parseDelayLevel exception", e); + log.info("levelString String = {}", levelString); + return false; + } + + return true; + } class DeliverDelayedMessageTimerTask extends TimerTask { private final int delayLevel; @@ -76,46 +238,12 @@ public void run() { } catch (Exception e) { log.error("executeOnTimeup exception", e); - ScheduleMessageService.this.timer.schedule(new DeliverDelayedMessageTimerTask(this.delayLevel, - this.offset), DELAY_FOR_A_PERIOD); + ScheduleMessageService.this.timer.schedule(new DeliverDelayedMessageTimerTask( + this.delayLevel, this.offset), DELAY_FOR_A_PERIOD); } } - private MessageExtBrokerInner messageTimeup(MessageExt msgExt) { - MessageExtBrokerInner msgInner = new MessageExtBrokerInner(); - msgInner.setBody(msgExt.getBody()); - msgInner.setFlag(msgExt.getFlag()); - msgInner.setProperties(msgExt.getProperties()); - - TopicFilterType topicFilterType = - (msgInner.getSysFlag() & MessageSysFlag.MultiTagsFlag) == MessageSysFlag.MultiTagsFlag ? TopicFilterType.MULTI_TAG - : TopicFilterType.SINGLE_TAG; - long tagsCodeValue = MessageExtBrokerInner.tagsString2tagsCode(topicFilterType, msgInner.getTags()); - msgInner.setTagsCode(tagsCodeValue); - msgInner.setPropertiesString(MessageDecoder.messageProperties2String(msgExt.getProperties())); - - msgInner.setSysFlag(msgExt.getSysFlag()); - msgInner.setBornTimestamp(msgExt.getBornTimestamp()); - msgInner.setBornHost(msgExt.getBornHost()); - msgInner.setStoreHost(msgExt.getStoreHost()); - msgInner.setReconsumeTimes(msgExt.getReconsumeTimes()); - - msgInner.setWaitStoreMsgOK(false); - msgInner.clearProperty(Message.PROPERTY_DELAY_TIME_LEVEL); - - // ָTopic - msgInner.setTopic(msgInner.getProperty(Message.PROPERTY_REAL_TOPIC)); - - // ָQueueId - String queueIdStr = msgInner.getProperty(Message.PROPERTY_REAL_QUEUE_ID); - int queueId = Integer.parseInt(queueIdStr); - msgInner.setQueueId(queueId); - - return msgInner; - } - - public void executeOnTimeup() { ConsumeQueue cq = ScheduleMessageService.this.defaultMessageStore.findConsumeQueue(SCHEDULE_TOPIC, @@ -131,29 +259,31 @@ public void executeOnTimeup() { int sizePy = bufferCQ.getByteBuffer().getInt(); long tagsCode = bufferCQ.getByteBuffer().getLong(); - // 洢tagsCodeʵһʱ + // 队列里存储的tagsCode实际是一个时间点 long deliverTimestamp = tagsCode; nextOffset = offset + (i / ConsumeQueue.CQStoreUnitSize); long countdown = deliverTimestamp - System.currentTimeMillis(); - // ʱ䵽ˣͶ + // 时间到了,该投递 if (countdown <= 0) { MessageExt msgExt = - ScheduleMessageService.this.defaultMessageStore.lookMessageByOffset(offsetPy, - sizePy); + ScheduleMessageService.this.defaultMessageStore.lookMessageByOffset( + offsetPy, sizePy); if (msgExt != null) { MessageExtBrokerInner msgInner = this.messageTimeup(msgExt); PutMessageResult putMessageResult = - ScheduleMessageService.this.defaultMessageStore.putMessage(msgInner); - // ɹ + ScheduleMessageService.this.defaultMessageStore + .putMessage(msgInner); + // 成功 if (putMessageResult != null && putMessageResult.getPutMessageStatus() == PutMessageStatus.PUT_OK) { continue; } - // ʧ + // 失败 else { - log.error("a message time up, but reput it failed, topic: {} msgId {}", + log.error( + "a message time up, but reput it failed, topic: {} msgId {}", msgExt.getTopic(), msgExt.getMsgId()); ScheduleMessageService.this.timer.schedule( new DeliverDelayedMessageTimerTask(this.delayLevel, nextOffset), @@ -163,10 +293,11 @@ public void executeOnTimeup() { } } } - // ʱδʱ + // 时候未到,继续定时 else { - ScheduleMessageService.this.timer.schedule(new DeliverDelayedMessageTimerTask( - this.delayLevel, nextOffset), countdown); + ScheduleMessageService.this.timer.schedule( + new DeliverDelayedMessageTimerTask(this.delayLevel, nextOffset), + countdown); ScheduleMessageService.this.updateOffset(this.delayLevel, nextOffset); return; } @@ -179,7 +310,7 @@ public void executeOnTimeup() { return; } finally { - // ͷԴ + // 必须释放资源 bufferCQ.release(); } } // end of if (bufferCQ != null) @@ -188,152 +319,38 @@ public void executeOnTimeup() { ScheduleMessageService.this.timer.schedule(new DeliverDelayedMessageTimerTask(this.delayLevel, this.offset), DELAY_FOR_A_WHILE); } - } - - - private void updateOffset(int delayLevel, long offset) { - this.offsetTable.put(delayLevel, offset); - } - - - public ScheduleMessageService(final DefaultMessageStore defaultMessageStore) { - this.defaultMessageStore = defaultMessageStore; - } - - - public static int queueId2DelayLevel(final int queueId) { - return queueId + 1; - } - public static int delayLevel2QueueId(final int delayLevel) { - return delayLevel - 1; - } - - - public long computeDeliverTimestamp(final int delayLevel, final long storeTimestamp) { - Long time = this.delayLevelTable.get(delayLevel); - if (time != null) { - return time + storeTimestamp; - } - - return storeTimestamp + 1000; - } - - - public boolean parseDelayLevel() { - HashMap timeUnitTable = new HashMap(); - timeUnitTable.put("s", 1000L); - timeUnitTable.put("m", 1000L * 60); - timeUnitTable.put("h", 1000L * 60 * 60); - timeUnitTable.put("d", 1000L * 60 * 60 * 24); - - String levelString = this.defaultMessageStore.getMessageStoreConfig().getMessageDelayLevel(); - try { - String[] levelArray = levelString.split(" "); - for (int i = 0; i < levelArray.length; i++) { - String value = levelArray[i]; - String ch = value.substring(value.length() - 1); - Long tu = timeUnitTable.get(ch); - - int level = i + 1; - if (level > this.maxDelayLevel) { - this.maxDelayLevel = level; - } - long num = Long.parseLong(value.substring(0, value.length() - 1)); - long delayTimeMillis = tu * num; - this.delayLevelTable.put(level, delayTimeMillis); - } - } - catch (Exception e) { - log.error("parseDelayLevel exception", e); - log.info("levelString String = {}", levelString); - return false; - } - - return true; - } - - - public boolean load() { - boolean result = this.parseDelayLevel(); - if (result) { - String str = MixAll.file2String(this.defaultMessageStore.getMessageStoreConfig().getDelayOffsetStorePath()); - if (str != null) { - Properties prop = MixAll.string2Properties(str); - if (prop != null) { - Set keyset = prop.keySet(); - for (Object object : keyset) { - String propValue = prop.getProperty(object.toString()); - if (propValue != null) { - this.updateOffset(Integer.parseInt(object.toString()), Long.parseLong(propValue)); - log.info("load delay offset table, LEVEL: {} OFFSET {}", object.toString(), propValue); - } - } - } - } - } - return result; - } - - - public void start() { - // ΪÿʱӶʱ - for (Integer level : this.delayLevelTable.keySet()) { - Long timeDelay = this.delayLevelTable.get(level); - Long offset = this.offsetTable.get(level); - if (null == offset) { - offset = 0L; - } + private MessageExtBrokerInner messageTimeup(MessageExt msgExt) { + MessageExtBrokerInner msgInner = new MessageExtBrokerInner(); + msgInner.setBody(msgExt.getBody()); + msgInner.setFlag(msgExt.getFlag()); + msgInner.setProperties(msgExt.getProperties()); - if (timeDelay != null) { - this.timer.schedule(new DeliverDelayedMessageTimerTask(level, offset), FIRST_DELAY_TIME); - } - } + TopicFilterType topicFilterType = MessageExt.parseTopicFilterType(msgInner.getSysFlag()); + long tagsCodeValue = + MessageExtBrokerInner.tagsString2tagsCode(topicFilterType, msgInner.getTags()); + msgInner.setTagsCode(tagsCodeValue); + msgInner.setPropertiesString(MessageDecoder.messageProperties2String(msgExt.getProperties())); - // ʱʱˢ - this.timer.scheduleAtFixedRate(new TimerTask() { + msgInner.setSysFlag(msgExt.getSysFlag()); + msgInner.setBornTimestamp(msgExt.getBornTimestamp()); + msgInner.setBornHost(msgExt.getBornHost()); + msgInner.setStoreHost(msgExt.getStoreHost()); + msgInner.setReconsumeTimes(msgExt.getReconsumeTimes()); - @Override - public void run() { - try { - ScheduleMessageService.this.flush(); - } - catch (Exception e) { - log.error("scheduleAtFixedRate flush exception", e); - } - } - }, 10000, this.defaultMessageStore.getMessageStoreConfig().getFlushDelayOffsetInterval()); - } + msgInner.setWaitStoreMsgOK(false); + msgInner.clearProperty(MessageConst.PROPERTY_DELAY_TIME_LEVEL); + // 恢复Topic + msgInner.setTopic(msgInner.getProperty(MessageConst.PROPERTY_REAL_TOPIC)); - private void flush() { - StringBuilder sb = new StringBuilder(); - for (Integer level : this.offsetTable.keySet()) { - Long offset = this.offsetTable.get(level); - if (null == offset) { - offset = 0L; - } + // 恢复QueueId + String queueIdStr = msgInner.getProperty(MessageConst.PROPERTY_REAL_QUEUE_ID); + int queueId = Integer.parseInt(queueIdStr); + msgInner.setQueueId(queueId); - sb.append(level + "=" + offset + IOUtils.LINE_SEPARATOR); + return msgInner; } - - if (sb.toString().length() == 0) - return; - - boolean result = - MixAll.string2File(sb.toString(), this.defaultMessageStore.getMessageStoreConfig() - .getDelayOffsetStorePath()); - log.info("flush delay offset table, {}", (result ? "SUCCESS" : "FAILED")); - } - - - public void shutdown() { - this.timer.cancel(); - } - - - public int getMaxDelayLevel() { - return maxDelayLevel; } } diff --git a/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/transaction/TransactionCheckExecuter.java b/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/transaction/TransactionCheckExecuter.java index f09ec98e..3ef55510 100644 --- a/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/transaction/TransactionCheckExecuter.java +++ b/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/transaction/TransactionCheckExecuter.java @@ -1,12 +1,25 @@ /** - * + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.store.transaction; /** - * 洢Producerز״̬ + * 存储层向Producer回查事务状态 * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * @author shijia.wxr + * @since 2013-7-21 */ public interface TransactionCheckExecuter { public void gotoCheck(// diff --git a/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/transaction/TransactionStateService.java b/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/transaction/TransactionStateService.java index 49770cbc..40e40039 100644 --- a/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/transaction/TransactionStateService.java +++ b/rocketmq-store/src/main/java/com/alibaba/rocketmq/store/transaction/TransactionStateService.java @@ -1,68 +1,83 @@ /** - * $Id: TransactionStateService.java 1831 2013-05-16 01:39:51Z shijia.wxr $ + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alibaba.rocketmq.store.transaction; import java.nio.ByteBuffer; import java.util.Iterator; import java.util.List; +import java.util.Timer; +import java.util.TimerTask; import java.util.TreeSet; import java.util.concurrent.atomic.AtomicLong; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.alibaba.rocketmq.common.Message; -import com.alibaba.rocketmq.common.MessageExt; -import com.alibaba.rocketmq.common.MixAll; +import com.alibaba.rocketmq.common.constant.LoggerName; +import com.alibaba.rocketmq.common.message.MessageConst; +import com.alibaba.rocketmq.common.message.MessageExt; import com.alibaba.rocketmq.common.sysflag.MessageSysFlag; import com.alibaba.rocketmq.store.ConsumeQueue; import com.alibaba.rocketmq.store.DefaultMessageStore; import com.alibaba.rocketmq.store.MapedFile; import com.alibaba.rocketmq.store.MapedFileQueue; import com.alibaba.rocketmq.store.SelectMapedBufferResult; +import com.alibaba.rocketmq.store.config.BrokerRole; /** - * 񣬴洢ÿ״̬PreparedCommitedRollbacked
- * ʽͣ
+ * 事务服务,存储每条事务的状态(Prepared,Commited,Rollbacked)
+ * 名词解释:
* clOffset - Commit Log Offset
* tsOffset - Transaction State Table Offset * - * @author vintage.wang@gmail.com shijia.wxr@taobao.com - * + * @author shijia.wxr + * @since 2013-7-21 */ public class TransactionStateService { - private static final Logger log = LoggerFactory.getLogger(MixAll.StoreLoggerName); - // 洢ԪС + // 存储单元大小 public static final int TSStoreUnitSize = 24; - // ָ״̬redolog + // 用来恢复事务状态表的redolog public static final String TRANSACTION_REDOLOG_TOPIC = "TRANSACTION_REDOLOG_TOPIC_XXXX"; public static final int TRANSACTION_REDOLOG_TOPIC_QUEUEID = 0; - // 洢 + public final static long PreparedMessageTagsCode = -1; + private static final Logger log = LoggerFactory.getLogger(LoggerName.StoreLoggerName); + // 更改事务状态,具体更改位置 + private final static int TS_STATE_POS = 20; + private static final Logger tranlog = LoggerFactory.getLogger(LoggerName.TransactionLoggerName); + // 存储顶层对象 private final DefaultMessageStore defaultMessageStore; - // 洢״̬ı - private MapedFileQueue tranStateTable; - // ظڴBuffer + // 重复利用内存Buffer private final ByteBuffer byteBufferAppend = ByteBuffer.allocate(TSStoreUnitSize); - // ״̬Redolog崵ͨredologָ״̬ - // RedologʵѶУҪΪ˻ָ + // 事务状态的Redolog,当进程意外宕掉,可通过redolog恢复所有事务的状态 + // Redolog的实现利用了消费队列,主要为了恢复方便 private final ConsumeQueue tranRedoLog; - public final static long PreparedMessageTagsCode = -1; - - // ״̬λ - private final static int TS_STATE_POS = 20; - - // State Table Offsetʱ + // State Table Offset,重启时,必须纠正 private final AtomicLong tranStateTableOffset = new AtomicLong(0); + // 定时回查线程 + private final Timer timer = new Timer("CheckTransactionMessageTimer", true); + // 存储事务状态的表格 + private MapedFileQueue tranStateTable; public TransactionStateService(final DefaultMessageStore defaultMessageStore) { this.defaultMessageStore = defaultMessageStore; this.tranStateTable = new MapedFileQueue(defaultMessageStore.getMessageStoreConfig().getTranStateTableStorePath(), - defaultMessageStore.getMessageStoreConfig().getTranStateTableMapedFileSize(), - defaultMessageStore.getAllocateMapedFileService()); + defaultMessageStore.getMessageStoreConfig().getTranStateTableMapedFileSize(), null); this.tranRedoLog = new ConsumeQueue(// TRANSACTION_REDOLOG_TOPIC,// @@ -81,6 +96,142 @@ public boolean load() { } + public void start() { + this.initTimerTask(); + } + + + private void initTimerTask() { + final List mapedFiles = this.tranStateTable.getMapedFiles(); + for (MapedFile mf : mapedFiles) { + this.addTimerTask(mf); + } + } + + + private void addTimerTask(final MapedFile mf) { + this.timer.scheduleAtFixedRate(new TimerTask() { + private final MapedFile mapedFile = mf; + private final TransactionCheckExecuter transactionCheckExecuter = + TransactionStateService.this.defaultMessageStore.getTransactionCheckExecuter(); + private final long checkTransactionMessageAtleastInterval = + TransactionStateService.this.defaultMessageStore.getMessageStoreConfig() + .getCheckTransactionMessageAtleastInterval(); + private final boolean slave = TransactionStateService.this.defaultMessageStore + .getMessageStoreConfig().getBrokerRole() == BrokerRole.SLAVE; + + + @Override + public void run() { + // Slave不需要回查事务状态 + if (slave) + return; + + // Check功能是否开启 + if (!TransactionStateService.this.defaultMessageStore.getMessageStoreConfig() + .isCheckTransactionMessageEnable()) { + return; + } + + try { + SelectMapedBufferResult selectMapedBufferResult = mapedFile.selectMapedBuffer(0); + if (selectMapedBufferResult != null) { + long preparedMessageCountInThisMapedFile = 0; + int i = 0; + try { + + for (; i < selectMapedBufferResult.getSize(); i += TSStoreUnitSize) { + selectMapedBufferResult.getByteBuffer().position(i); + + // Commit Log Offset + long clOffset = selectMapedBufferResult.getByteBuffer().getLong(); + // Message Size + int msgSize = selectMapedBufferResult.getByteBuffer().getInt(); + // Timestamp + int timestamp = selectMapedBufferResult.getByteBuffer().getInt(); + // Producer Group Hashcode + int groupHashCode = selectMapedBufferResult.getByteBuffer().getInt(); + // Transaction State + int tranType = selectMapedBufferResult.getByteBuffer().getInt(); + + // 已经提交或者回滚的消息跳过 + if (tranType != MessageSysFlag.TransactionPreparedType) { + continue; + } + + // 遇到时间不符合,终止 + long timestampLong = timestamp * 1000; + long diff = System.currentTimeMillis() - timestampLong; + if (diff < checkTransactionMessageAtleastInterval) { + break; + } + + preparedMessageCountInThisMapedFile++; + + try { + this.transactionCheckExecuter.gotoCheck(// + groupHashCode,// + getTranStateOffset(i),// + clOffset,// + msgSize); + } + catch (Exception e) { + tranlog.warn("gotoCheck Exception", e); + } + } + + // 无Prepared消息,且遍历完,则终止定时任务 + if (0 == preparedMessageCountInThisMapedFile // + && i == mapedFile.getFileSize()) { + tranlog + .info( + "remove the transaction timer task, because no prepared message in this mapedfile[{}]", + mapedFile.getFileName()); + this.cancel(); + } + } + finally { + selectMapedBufferResult.release(); + } + + tranlog + .info( + "the transaction timer task execute over in this period, {} Prepared Message: {} Check Progress: {}/{}", + mapedFile.getFileName(),// + preparedMessageCountInThisMapedFile,// + i / TSStoreUnitSize,// + mapedFile.getFileSize() / TSStoreUnitSize// + ); + } + else if (mapedFile.isFull()) { + tranlog.info("the mapedfile[{}] maybe deleted, cancel check transaction timer task", + mapedFile.getFileName()); + this.cancel(); + return; + } + } + catch (Exception e) { + log.error("check transaction timer task Exception", e); + } + } + + + private long getTranStateOffset(final long currentIndex) { + long offset = + (this.mapedFile.getFileFromOffset() + currentIndex) + / TransactionStateService.TSStoreUnitSize; + return offset; + } + }, 1000 * 60, this.defaultMessageStore.getMessageStoreConfig() + .getCheckTransactionMessageTimerInterval()); + } + + + public void shutdown() { + this.timer.cancel(); + } + + public int deleteExpiredStateFile(long offset) { int cnt = this.tranStateTable.deleteExpiredFileByOffset(offset, TSStoreUnitSize); return cnt; @@ -92,9 +243,9 @@ public void recoverStateTable(final boolean lastExitOK) { this.recoverStateTableNormal(); } else { - // һɾState Table + // 第一步,删除State Table this.tranStateTable.destroy(); - // ڶͨRedoLogȫָStateTable + // 第二步,通过RedoLog全量恢复StateTable this.recreateStateTable(); } } @@ -103,12 +254,11 @@ public void recoverStateTable(final boolean lastExitOK) { private void recreateStateTable() { this.tranStateTable = new MapedFileQueue(defaultMessageStore.getMessageStoreConfig().getTranStateTableStorePath(), - defaultMessageStore.getMessageStoreConfig().getTranStateTableMapedFileSize(), - defaultMessageStore.getAllocateMapedFileService()); + defaultMessageStore.getMessageStoreConfig().getTranStateTableMapedFileSize(), null); final TreeSet preparedItemSet = new TreeSet(); - // һͷɨRedoLog + // 第一步,重头扫描RedoLog final long minOffset = this.tranRedoLog.getMinOffsetInQuque(); long processOffset = minOffset; while (true) { @@ -134,7 +284,7 @@ private void recreateStateTable() { processOffset += i; } finally { - // ͷԴ + // 必须释放资源 bufferConsumeQueue.release(); } } @@ -143,25 +293,65 @@ private void recreateStateTable() { } } - log.info("scan transaction redolog over, End offset: {}, Prepared Transaction Count: {}", processOffset, - preparedItemSet.size()); - // ڶؽStateTable + log.info("scan transaction redolog over, End offset: {}, Prepared Transaction Count: {}", + processOffset, preparedItemSet.size()); + // 第二步,重建StateTable Iterator it = preparedItemSet.iterator(); while (it.hasNext()) { Long offset = it.next(); MessageExt msgExt = this.defaultMessageStore.lookMessageByOffset(offset); if (msgExt != null) { - this.appendPreparedTransaction(msgExt.getCommitLogOffset(), msgExt.getStoreSize(), (int) (msgExt - .getStoreTimestamp() / 1000), msgExt.getProperty(Message.PROPERTY_PRODUCER_GROUP).hashCode()); + this.appendPreparedTransaction(msgExt.getCommitLogOffset(), msgExt.getStoreSize(), + (int) (msgExt.getStoreTimestamp() / 1000), + msgExt.getProperty(MessageConst.PROPERTY_PRODUCER_GROUP).hashCode()); + this.tranStateTableOffset.incrementAndGet(); } } } + /** + * 单线程调用 + */ + public boolean appendPreparedTransaction(// + final long clOffset,// + final int size,// + final int timestamp,// + final int groupHashCode// + ) { + MapedFile mapedFile = this.tranStateTable.getLastMapedFile(); + if (null == mapedFile) { + log.error("appendPreparedTransaction: create mapedfile error."); + return false; + } + + // 首次创建,加入定时任务中 + if (0 == mapedFile.getWrotePostion()) { + this.addTimerTask(mapedFile); + } + + this.byteBufferAppend.position(0); + this.byteBufferAppend.limit(TSStoreUnitSize); + + // Commit Log Offset + this.byteBufferAppend.putLong(clOffset); + // Message Size + this.byteBufferAppend.putInt(size); + // Timestamp + this.byteBufferAppend.putInt(timestamp); + // Producer Group Hashcode + this.byteBufferAppend.putInt(groupHashCode); + // Transaction State + this.byteBufferAppend.putInt(MessageSysFlag.TransactionPreparedType); + + return mapedFile.appendMessage(this.byteBufferAppend.array()); + } + + private void recoverStateTableNormal() { final List mapedFiles = this.tranStateTable.getMapedFiles(); if (!mapedFiles.isEmpty()) { - // ӵļʼָ + // 从倒数第三个文件开始恢复 int index = mapedFiles.size() - 3; if (index < 0) index = 0; @@ -173,28 +363,44 @@ private void recoverStateTableNormal() { long mapedFileOffset = 0; while (true) { for (int i = 0; i < mapedFileSizeLogics; i += TSStoreUnitSize) { - long offset = byteBuffer.getLong(); - int size = byteBuffer.getInt(); - long tagsCode = byteBuffer.getLong(); - // ˵ǰ洢ԪЧ - // TODO жЧǷ - if (offset >= 0 && size > 0) { + final long clOffset_read = byteBuffer.getLong(); + final int size_read = byteBuffer.getInt(); + final int timestamp_read = byteBuffer.getInt(); + final int groupHashCode_read = byteBuffer.getInt(); + final int state_read = byteBuffer.getInt(); + + boolean stateOK = false; + switch (state_read) { + case MessageSysFlag.TransactionPreparedType: + case MessageSysFlag.TransactionCommitType: + case MessageSysFlag.TransactionRollbackType: + stateOK = true; + break; + default: + break; + } + + // 说明当前存储单元有效 + // TODO 这样判断有效是否合理? + if (clOffset_read >= 0 && size_read > 0 && stateOK) { mapedFileOffset = i + TSStoreUnitSize; } else { - log.info("recover current logics file over, " + mapedFile.getFileName() + " " + offset - + " " + size + " " + tagsCode); + log.info("recover current transaction state table file over, " + + mapedFile.getFileName() + " " + clOffset_read + " " + size_read + " " + + timestamp_read); break; } } - // ߵļĩβлһļ + // 走到文件末尾,切换至下一个文件 if (mapedFileOffset == mapedFileSizeLogics) { index++; if (index >= mapedFiles.size()) { - // ǰ֧ܷ - log.info("recover last logics file over, last maped file " + mapedFile.getFileName()); + // 当前条件分支不可能发生 + log.info("recover last transaction state table file over, last maped file " + + mapedFile.getFileName()); break; } else { @@ -202,57 +408,27 @@ private void recoverStateTableNormal() { byteBuffer = mapedFile.sliceByteBuffer(); processOffset = mapedFile.getFileFromOffset(); mapedFileOffset = 0; - log.info("recover next logics file, " + mapedFile.getFileName()); + log.info("recover next transaction state table file, " + mapedFile.getFileName()); } } else { - log.info("recover current logics queue over " + mapedFile.getFileName() + " " - + (processOffset + mapedFileOffset)); + log.info("recover current transaction state table queue over " + mapedFile.getFileName() + + " " + (processOffset + mapedFileOffset)); break; } } processOffset += mapedFileOffset; this.tranStateTable.truncateDirtyFiles(processOffset); + this.tranStateTableOffset.set(this.tranStateTable.getMaxOffset() / TSStoreUnitSize); + log.info("recover normal over, transaction state table max offset: {}", + this.tranStateTableOffset.get()); } } /** - * ̵߳ - */ - public boolean appendPreparedTransaction(// - final long clOffset,// - final int size,// - final int timestamp,// - final int groupHashCode// - ) { - MapedFile mapedFile = this.tranStateTable.getLastMapedFile(); - if (null == mapedFile) { - log.error("appendPreparedTransaction: create mapedfile error."); - return false; - } - - this.byteBufferAppend.position(0); - this.byteBufferAppend.limit(TSStoreUnitSize); - - // Commit Log Offset - this.byteBufferAppend.putLong(clOffset); - // Message Size - this.byteBufferAppend.putInt(size); - // Timestamp - this.byteBufferAppend.putInt(timestamp); - // Producer Group Hashcode - this.byteBufferAppend.putInt(groupHashCode); - // Transaction State - this.byteBufferAppend.putInt(MessageSysFlag.TransactionPreparedType); - - return mapedFile.appendMessage(this.byteBufferAppend.array()); - } - - - /** - * ̵߳ + * 单线程调用 */ public boolean updateTransactionState(// final long tsOffset,// @@ -269,27 +445,27 @@ public boolean updateTransactionState(// final int groupHashCode_read = selectMapedBufferResult.getByteBuffer().getInt(); final int state_read = selectMapedBufferResult.getByteBuffer().getInt(); - // Уȷ + // 校验数据正确性 if (clOffset != clOffset_read) { log.error("updateTransactionState error clOffset: {} clOffset_read: {}", clOffset, clOffset_read); return false; } - // Уȷ + // 校验数据正确性 if (groupHashCode != groupHashCode_read) { log.error("updateTransactionState error groupHashCode: {} groupHashCode_read: {}", groupHashCode, groupHashCode_read); return false; } - // жǷѾ¹ + // 判断是否已经更新过 if (MessageSysFlag.TransactionPreparedType != state_read) { log.warn("updateTransactionState error, the transaction is updated before."); return true; } - // ״̬ + // 更新事务状态 selectMapedBufferResult.getByteBuffer().putInt(TS_STATE_POS, state); } catch (Exception e) { diff --git a/rocketmq-store/src/test/java/com/alibaba/rocketmq/store/DefaultMessageStoreTest.java b/rocketmq-store/src/test/java/com/alibaba/rocketmq/store/DefaultMessageStoreTest.java index 905e31be..5da6596f 100644 --- a/rocketmq-store/src/test/java/com/alibaba/rocketmq/store/DefaultMessageStoreTest.java +++ b/rocketmq-store/src/test/java/com/alibaba/rocketmq/store/DefaultMessageStoreTest.java @@ -16,18 +16,18 @@ /** - * @author vintage.wang@gmail.com shijia.wxr@taobao.com + * @author shijia.wxr */ public class DefaultMessageStoreTest { - // и + // 队列个数 private static int QUEUE_TOTAL = 100; - // ĸ + // 发往哪个队列 private static AtomicInteger QueueId = new AtomicInteger(0); - // ַ + // 发送主机地址 private static SocketAddress BornHost; - // 洢ַ + // 存储主机地址 private static SocketAddress StoreHost; - // Ϣ + // 消息体 private static byte[] MessageBody; private static final String StoreMessage = "Once, there was a chance for me!"; @@ -69,22 +69,22 @@ public void test_write_read() throws Exception { long totalMsgs = 10000; QUEUE_TOTAL = 1; - // Ϣ + // 构造消息体 MessageBody = StoreMessage.getBytes(); MessageStoreConfig messageStoreConfig = new MessageStoreConfig(); - // ÿӳļ 4K + // 每个物理映射文件 4K messageStoreConfig.setMapedFileSizeCommitLog(1024 * 8); messageStoreConfig.setMapedFileSizeConsumeQueue(1024 * 4); messageStoreConfig.setMaxHashSlotNum(100); messageStoreConfig.setMaxIndexNum(100 * 10); MessageStore master = new DefaultMessageStore(messageStoreConfig); - // һload + // 第一步,load已有数据 boolean load = master.load(); assertTrue(load); - // ڶ + // 第二步,启动服务 master.start(); for (long i = 0; i < totalMsgs; i++) { PutMessageResult result = master.putMessage(buildMessage()); @@ -92,7 +92,7 @@ public void test_write_read() throws Exception { System.out.println(i + "\t" + result.getAppendMessageResult().getMsgId()); } - // ʼļ + // 开始读文件 for (long i = 0; i < totalMsgs; i++) { try { GetMessageResult result = master.getMessage("TOPIC_A", 0, i, 1024 * 1024, null); @@ -109,10 +109,10 @@ public void test_write_read() throws Exception { } - // رմ洢 + // 关闭存储服务 master.shutdown(); - // ɾļ + // 删除文件 master.destroy(); System.out.println("================================================================"); } @@ -124,22 +124,22 @@ public void test_group_commit() throws Exception { long totalMsgs = 10000; QUEUE_TOTAL = 1; - // Ϣ + // 构造消息体 MessageBody = StoreMessage.getBytes(); MessageStoreConfig messageStoreConfig = new MessageStoreConfig(); - // ÿӳļ 4K + // 每个物理映射文件 4K messageStoreConfig.setMapedFileSizeCommitLog(1024 * 8); - // GroupCommit + // 开启GroupCommit功能 messageStoreConfig.setFlushDiskType(FlushDiskType.SYNC_FLUSH); MessageStore master = new DefaultMessageStore(messageStoreConfig); - // һload + // 第一步,load已有数据 boolean load = master.load(); assertTrue(load); - // ڶ + // 第二步,启动服务 master.start(); for (long i = 0; i < totalMsgs; i++) { PutMessageResult result = master.putMessage(buildMessage()); @@ -147,7 +147,7 @@ public void test_group_commit() throws Exception { System.out.println(i + "\t" + result.getAppendMessageResult().getMsgId()); } - // ʼļ + // 开始读文件 for (long i = 0; i < totalMsgs; i++) { try { GetMessageResult result = master.getMessage("TOPIC_A", 0, i, 1024 * 1024, null); @@ -164,10 +164,10 @@ public void test_group_commit() throws Exception { } - // رմ洢 + // 关闭存储服务 master.shutdown(); - // ɾļ + // 删除文件 master.destroy(); System.out.println("================================================================"); } diff --git a/rocketmq-store/src/test/java/com/alibaba/rocketmq/store/MapedFileQueueTest.java b/rocketmq-store/src/test/java/com/alibaba/rocketmq/store/MapedFileQueueTest.java index d8afdcfb..8f89e41c 100644 --- a/rocketmq-store/src/test/java/com/alibaba/rocketmq/store/MapedFileQueueTest.java +++ b/rocketmq-store/src/test/java/com/alibaba/rocketmq/store/MapedFileQueueTest.java @@ -3,7 +3,9 @@ */ package com.alibaba.rocketmq.store; -import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; import org.junit.After; import org.junit.AfterClass; @@ -43,7 +45,8 @@ public void test_getLastMapedFile() { System.out.println("================================================================"); AllocateMapedFileService allocateMapedFileService = new AllocateMapedFileService(); allocateMapedFileService.start(); - MapedFileQueue mapedFileQueue = new MapedFileQueue("./unit_test_store/a/", 1024, allocateMapedFileService); + MapedFileQueue mapedFileQueue = + new MapedFileQueue("./unit_test_store/a/", 1024, allocateMapedFileService); for (int i = 0; i < 1024; i++) { MapedFile mapedFile = mapedFileQueue.getLastMapedFile(); @@ -68,7 +71,8 @@ public void test_findMapedFileByOffset() { System.out.println("================================================================"); AllocateMapedFileService allocateMapedFileService = new AllocateMapedFileService(); allocateMapedFileService.start(); - MapedFileQueue mapedFileQueue = new MapedFileQueue("./unit_test_store/b/", 1024, allocateMapedFileService); + MapedFileQueue mapedFileQueue = + new MapedFileQueue("./unit_test_store/b/", 1024, allocateMapedFileService); for (int i = 0; i < 1024; i++) { MapedFile mapedFile = mapedFileQueue.getLastMapedFile(); @@ -127,7 +131,8 @@ public void test_commit() { System.out.println("================================================================"); AllocateMapedFileService allocateMapedFileService = new AllocateMapedFileService(); allocateMapedFileService.start(); - MapedFileQueue mapedFileQueue = new MapedFileQueue("./unit_test_store/c/", 1024, allocateMapedFileService); + MapedFileQueue mapedFileQueue = + new MapedFileQueue("./unit_test_store/c/", 1024, allocateMapedFileService); for (int i = 0; i < 1024; i++) { MapedFile mapedFile = mapedFileQueue.getLastMapedFile(); @@ -136,7 +141,7 @@ public void test_commit() { assertTrue(result); } - // ϳύ + // 不断尝试提交 boolean result = mapedFileQueue.commit(0); assertFalse(result); assertEquals(1024 * 1, mapedFileQueue.getCommittedWhere()); @@ -180,7 +185,8 @@ public void test_getMapedMemorySize() { System.out.println("================================================================"); AllocateMapedFileService allocateMapedFileService = new AllocateMapedFileService(); allocateMapedFileService.start(); - MapedFileQueue mapedFileQueue = new MapedFileQueue("./unit_test_store/d/", 1024, allocateMapedFileService); + MapedFileQueue mapedFileQueue = + new MapedFileQueue("./unit_test_store/d/", 1024, allocateMapedFileService); for (int i = 0; i < 1024; i++) { MapedFile mapedFile = mapedFileQueue.getLastMapedFile(); diff --git a/rocketmq-store/src/test/java/com/alibaba/rocketmq/store/MapedFileTest.java b/rocketmq-store/src/test/java/com/alibaba/rocketmq/store/MapedFileTest.java index 8db6ba81..983c1a38 100644 --- a/rocketmq-store/src/test/java/com/alibaba/rocketmq/store/MapedFileTest.java +++ b/rocketmq-store/src/test/java/com/alibaba/rocketmq/store/MapedFileTest.java @@ -45,19 +45,19 @@ public void test_write_read() { System.out.println("Read: " + readString); assertTrue(readString.equals(StoreMessage)); - // ֹBufferд + // 禁止Buffer读写 mapedFile.shutdown(1000); - // mapedFile󲻿 + // mapedFile对象不可用 assertTrue(!mapedFile.isAvailable()); - // ͷŶBuffer + // 释放读到的Buffer selectMapedBufferResult.release(); - // ڴͷŵ + // 内存真正释放掉 assertTrue(mapedFile.isCleanupOver()); - // ļɾɹ + // 文件删除成功 assertTrue(mapedFile.destroy(1000)); } catch (IOException e) { @@ -67,7 +67,7 @@ public void test_write_read() { /** - * ǰڶmmap󣬻ᵼJVM CRASHED + * 当前测试用例由于对mmap操作错误,会导致JVM CRASHED */ @Ignore public void test_jvm_crashed() { diff --git a/rocketmq-store/src/test/java/com/alibaba/rocketmq/store/RecoverTest.java b/rocketmq-store/src/test/java/com/alibaba/rocketmq/store/RecoverTest.java index 1a44063a..afa6aee3 100644 --- a/rocketmq-store/src/test/java/com/alibaba/rocketmq/store/RecoverTest.java +++ b/rocketmq-store/src/test/java/com/alibaba/rocketmq/store/RecoverTest.java @@ -16,21 +16,21 @@ import org.junit.BeforeClass; import org.junit.Test; -import com.alibaba.rocketmq.common.MessageExt; -import com.alibaba.rocketmq.common.MessageDecoder; +import com.alibaba.rocketmq.common.message.MessageDecoder; +import com.alibaba.rocketmq.common.message.MessageExt; import com.alibaba.rocketmq.store.config.MessageStoreConfig; public class RecoverTest { - // и + // 队列个数 private static int QUEUE_TOTAL = 10; - // ĸ + // 发往哪个队列 private static AtomicInteger QueueId = new AtomicInteger(0); - // ַ + // 发送主机地址 private static SocketAddress BornHost; - // 洢ַ + // 存储主机地址 private static SocketAddress StoreHost; - // Ϣ + // 消息体 private static byte[] MessageBody; private static final String StoreMessage = "Once, there was a chance for me!aaaaaaaaaaaaaaaaaaaaaaaa"; @@ -71,23 +71,23 @@ public static void tearDownAfterClass() throws Exception { private void destroy() { if (storeWrite1 != null) { - // رմ洢 + // 关闭存储服务 storeWrite1.shutdown(); - // ɾļ + // 删除文件 storeWrite1.destroy(); } if (storeWrite2 != null) { - // رմ洢 + // 关闭存储服务 storeWrite2.shutdown(); - // ɾļ + // 删除文件 storeWrite2.destroy(); } if (storeRead != null) { - // رմ洢 + // 关闭存储服务 storeRead.shutdown(); - // ɾļ + // 删除文件 storeRead.destroy(); } } @@ -98,13 +98,13 @@ public void writeMessage(boolean normal, boolean first) throws Exception { long totalMsgs = 1000; QUEUE_TOTAL = 3; - // Ϣ + // 构造消息体 MessageBody = StoreMessage.getBytes(); MessageStoreConfig messageStoreConfig = new MessageStoreConfig(); - // ÿӳļ + // 每个物理映射文件 messageStoreConfig.setMapedFileSizeCommitLog(1024 * 32); - // ÿ߼ӳļ + // 每个逻辑映射文件 messageStoreConfig.setMapedFileSizeConsumeQueue(100 * 20); messageStoreConfig.setMessageIndexEnable(false); @@ -116,14 +116,14 @@ public void writeMessage(boolean normal, boolean first) throws Exception { this.storeWrite2 = messageStore; } - // һload + // 第一步,load已有数据 boolean loadResult = messageStore.load(); assertTrue(loadResult); - // ڶ + // 第二步,启动服务 messageStore.start(); - // Ϣ + // 第三步,发消息 for (long i = 0; i < totalMsgs; i++) { PutMessageResult result = messageStore.putMessage(buildMessage()); @@ -132,7 +132,7 @@ public void writeMessage(boolean normal, boolean first) throws Exception { } if (normal) { - // رմ洢 + // 关闭存储服务 messageStore.shutdown(); } @@ -157,25 +157,25 @@ public void readMessage(final long msgCnt) throws Exception { System.out.println("================================================================"); QUEUE_TOTAL = 3; - // Ϣ + // 构造消息体 MessageBody = StoreMessage.getBytes(); MessageStoreConfig messageStoreConfig = new MessageStoreConfig(); - // ÿӳļ + // 每个物理映射文件 messageStoreConfig.setMapedFileSizeCommitLog(1024 * 32); - // ÿ߼ӳļ + // 每个逻辑映射文件 messageStoreConfig.setMapedFileSizeConsumeQueue(100 * 20); messageStoreConfig.setMessageIndexEnable(false); storeRead = new DefaultMessageStore(messageStoreConfig); - // һload + // 第一步,load已有数据 boolean loadResult = storeRead.load(); assertTrue(loadResult); - // ڶ + // 第二步,启动服务 storeRead.start(); - // Ϣ + // 第三步,收消息 long readCnt = 0; for (int queueId = 0; queueId < QUEUE_TOTAL; queueId++) { for (long offset = 0;;) { @@ -201,7 +201,7 @@ public void readMessage(final long msgCnt) throws Exception { /** - * رպָϢ֤ǷϢʧ + * 正常关闭后,重启恢复消息,验证是否有消息丢失 */ @Test public void test_recover_normally() throws Exception { @@ -213,7 +213,7 @@ public void test_recover_normally() throws Exception { /** - * رպָϢٴдϢ֤ǷϢʧ + * 正常关闭后,重启恢复消息,并再次写入消息,验证是否有消息丢失 */ @Test public void test_recover_normally_write() throws Exception { @@ -227,7 +227,7 @@ public void test_recover_normally_write() throws Exception { /** - * 쳣رպָϢ֤ǷϢʧ + * 异常关闭后,重启恢复消息,验证是否有消息丢失 */ @Test public void test_recover_abnormally() throws Exception { @@ -239,7 +239,7 @@ public void test_recover_abnormally() throws Exception { /** - * 쳣رպָϢٴдϢ֤ǷϢʧ + * 异常关闭后,重启恢复消息,并再次写入消息,验证是否有消息丢失 */ @Test public void test_recover_abnormally_write() throws Exception { diff --git a/rocketmq-store/src/test/java/com/alibaba/rocketmq/store/index/IndexFileTest.java b/rocketmq-store/src/test/java/com/alibaba/rocketmq/store/index/IndexFileTest.java index af0e86f5..9c4eaf82 100644 --- a/rocketmq-store/src/test/java/com/alibaba/rocketmq/store/index/IndexFileTest.java +++ b/rocketmq-store/src/test/java/com/alibaba/rocketmq/store/index/IndexFileTest.java @@ -22,17 +22,17 @@ public void test_put_index() { try { IndexFile indexFile = new IndexFile("100", hashSlotNum, indexNum, 0, 0); - // д + // 写入索引 for (long i = 0; i < (indexNum - 1); i++) { boolean putResult = indexFile.putKey(Long.toString(i), i, System.currentTimeMillis()); assertTrue(putResult); } - // ļѾˣ дʧ + // 索引文件已经满了, 再写入会失败 boolean putResult = indexFile.putKey(Long.toString(400), 400, System.currentTimeMillis()); assertFalse(putResult); - // ɾļ + // 删除文件 indexFile.destroy(0); } catch (Exception e) { @@ -47,17 +47,17 @@ public void test_put_get_index() { try { IndexFile indexFile = new IndexFile("200", hashSlotNum, indexNum, 0, 0); - // д + // 写入索引 for (long i = 0; i < (indexNum - 1); i++) { boolean putResult = indexFile.putKey(Long.toString(i), i, System.currentTimeMillis()); assertTrue(putResult); } - // ļѾˣ дʧ + // 索引文件已经满了, 再写入会失败 boolean putResult = indexFile.putKey(Long.toString(400), 400, System.currentTimeMillis()); assertFalse(putResult); - // + // 读索引 final List phyOffsets = new ArrayList(); indexFile.selectPhyOffset(phyOffsets, "60", 10, 0, Long.MAX_VALUE, true); for (Long offset : phyOffsets) { @@ -66,7 +66,7 @@ public void test_put_get_index() { assertFalse(phyOffsets.isEmpty()); - // ɾļ + // 删除文件 indexFile.destroy(0); } catch (Exception e) { diff --git a/rocketmq-store/src/test/java/com/alibaba/rocketmq/store/schedule/ScheduleMessageTest.java b/rocketmq-store/src/test/java/com/alibaba/rocketmq/store/schedule/ScheduleMessageTest.java index cd5808b1..9c4465b7 100644 --- a/rocketmq-store/src/test/java/com/alibaba/rocketmq/store/schedule/ScheduleMessageTest.java +++ b/rocketmq-store/src/test/java/com/alibaba/rocketmq/store/schedule/ScheduleMessageTest.java @@ -23,15 +23,15 @@ public class ScheduleMessageTest { - // и + // 队列个数 private static int QUEUE_TOTAL = 100; - // ĸ + // 发往哪个队列 private static AtomicInteger QueueId = new AtomicInteger(0); - // ַ + // 发送主机地址 private static SocketAddress BornHost; - // 洢ַ + // 存储主机地址 private static SocketAddress StoreHost; - // Ϣ + // 消息体 private static byte[] MessageBody; private static final String StoreMessage = "Once, there was a chance for me!"; @@ -72,22 +72,22 @@ public void test_delay_message() throws Exception { long totalMsgs = 10000; QUEUE_TOTAL = 32; - // Ϣ + // 构造消息体 MessageBody = StoreMessage.getBytes(); MessageStoreConfig messageStoreConfig = new MessageStoreConfig(); - // ÿӳļ 4K + // 每个物理映射文件 4K messageStoreConfig.setMapedFileSizeCommitLog(1024 * 32); messageStoreConfig.setMapedFileSizeConsumeQueue(1024 * 16); messageStoreConfig.setMaxHashSlotNum(100); messageStoreConfig.setMaxIndexNum(1000 * 10); MessageStore master = new DefaultMessageStore(messageStoreConfig); - // һload + // 第一步,load已有数据 boolean load = master.load(); assertTrue(load); - // ڶ + // 第二步,启动服务 master.start(); for (int i = 0; i < totalMsgs; i++) { MessageExtBrokerInner msg = buildMessage(); @@ -100,7 +100,7 @@ public void test_delay_message() throws Exception { System.out.println("write message over, wait time up"); Thread.sleep(1000 * 20); - // ʼļ + // 开始读文件 for (long i = 0; i < totalMsgs; i++) { try { GetMessageResult result = master.getMessage("TOPIC_A", 0, i, 1024 * 1024, null); @@ -119,10 +119,10 @@ public void test_delay_message() throws Exception { Thread.sleep(1000 * 15); - // رմ洢 + // 关闭存储服务 master.shutdown(); - // ɾļ + // 删除文件 master.destroy(); System.out.println("================================================================"); } diff --git a/rocketmq-store/vm.txt b/rocketmq-store/vm.txt deleted file mode 100644 index 25c080f5..00000000 --- a/rocketmq-store/vm.txt +++ /dev/null @@ -1,11 +0,0 @@ -sudo sysctl vm.overcommit_memory=1 -sudo sysctl vm.min_free_kbytes=7000000 -sudo sysctl vm.drop_caches=1 -sudo sysctl vm.zone_reclaim_mode=1 -sudo sysctl vm.max_map_count=655360 -sudo sysctl vm.dirty_background_bytes=20000000000 -sudo sysctl vm.dirty_bytes=20000000000 -sudo sysctl vm.page-cluster=3 -sudo sysctl vm.dirty_writeback_centisecs=360000 -sudo sysctl vm.enable_context_readahead=1 -sudo sysctl vm.swappiness=10 \ No newline at end of file diff --git a/rocketmq-tools/pom.xml b/rocketmq-tools/pom.xml index 16b66cf7..8d680c5a 100644 --- a/rocketmq-tools/pom.xml +++ b/rocketmq-tools/pom.xml @@ -1,14 +1,12 @@ - + com.alibaba.rocketmq rocketmq-all - 3.0.0-SNAPSHOT + 3.0.8-SNAPSHOT 4.0.0 jar - com.alibaba.rocketmq rocketmq-tools rocketmq-tools ${project.version} @@ -20,11 +18,23 @@ ${project.groupId} - rocketmq-common + rocketmq-client ${project.groupId} rocketmq-store + + com.alibaba + fastjson + + + ch.qos.logback + logback-classic + + + ch.qos.logback + logback-core + diff --git a/rocketmq-tools/src/main/java/com/alibaba/rocketmq/tools/admin/DefaultMQAdminExt.java b/rocketmq-tools/src/main/java/com/alibaba/rocketmq/tools/admin/DefaultMQAdminExt.java new file mode 100644 index 00000000..daf384e3 --- /dev/null +++ b/rocketmq-tools/src/main/java/com/alibaba/rocketmq/tools/admin/DefaultMQAdminExt.java @@ -0,0 +1,351 @@ +/** + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.rocketmq.tools.admin; + +import java.io.UnsupportedEncodingException; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.Set; + +import com.alibaba.rocketmq.client.ClientConfig; +import com.alibaba.rocketmq.client.QueryResult; +import com.alibaba.rocketmq.client.exception.MQBrokerException; +import com.alibaba.rocketmq.client.exception.MQClientException; +import com.alibaba.rocketmq.common.MixAll; +import com.alibaba.rocketmq.common.TopicConfig; +import com.alibaba.rocketmq.common.admin.ConsumeStats; +import com.alibaba.rocketmq.common.admin.RollbackStats; +import com.alibaba.rocketmq.common.admin.TopicStatsTable; +import com.alibaba.rocketmq.common.message.MessageExt; +import com.alibaba.rocketmq.common.message.MessageQueue; +import com.alibaba.rocketmq.common.protocol.body.ClusterInfo; +import com.alibaba.rocketmq.common.protocol.body.ConsumeByWho; +import com.alibaba.rocketmq.common.protocol.body.ConsumerConnection; +import com.alibaba.rocketmq.common.protocol.body.KVTable; +import com.alibaba.rocketmq.common.protocol.body.ProducerConnection; +import com.alibaba.rocketmq.common.protocol.body.TopicList; +import com.alibaba.rocketmq.common.protocol.route.TopicRouteData; +import com.alibaba.rocketmq.common.subscription.SubscriptionGroupConfig; +import com.alibaba.rocketmq.remoting.exception.RemotingCommandException; +import com.alibaba.rocketmq.remoting.exception.RemotingConnectException; +import com.alibaba.rocketmq.remoting.exception.RemotingException; +import com.alibaba.rocketmq.remoting.exception.RemotingSendRequestException; +import com.alibaba.rocketmq.remoting.exception.RemotingTimeoutException; + + +/** + * 所有运维接口都在这里实现 + * + * @author shijia.wxr + * @since 2013-7-14 + */ +public class DefaultMQAdminExt extends ClientConfig implements MQAdminExt { + private final DefaultMQAdminExtImpl defaultMQAdminExtImpl = new DefaultMQAdminExtImpl(this); + private String adminExtGroup = "admin_ext_group"; + private String createTopicKey = MixAll.DEFAULT_TOPIC; + + + public DefaultMQAdminExt() { + } + + + public DefaultMQAdminExt(final String adminExtGroup) { + this.adminExtGroup = adminExtGroup; + } + + + @Override + public void createTopic(String key, String newTopic, int queueNum) throws MQClientException { + defaultMQAdminExtImpl.createTopic(key, newTopic, queueNum); + } + + + @Override + public long searchOffset(MessageQueue mq, long timestamp) throws MQClientException { + return defaultMQAdminExtImpl.searchOffset(mq, timestamp); + } + + + @Override + public long maxOffset(MessageQueue mq) throws MQClientException { + return defaultMQAdminExtImpl.maxOffset(mq); + } + + + @Override + public long minOffset(MessageQueue mq) throws MQClientException { + return defaultMQAdminExtImpl.minOffset(mq); + } + + + @Override + public long earliestMsgStoreTime(MessageQueue mq) throws MQClientException { + return defaultMQAdminExtImpl.earliestMsgStoreTime(mq); + } + + + @Override + public MessageExt viewMessage(String msgId) throws RemotingException, MQBrokerException, + InterruptedException, MQClientException { + return defaultMQAdminExtImpl.viewMessage(msgId); + } + + + @Override + public QueryResult queryMessage(String topic, String key, int maxNum, long begin, long end) + throws MQClientException, InterruptedException { + return defaultMQAdminExtImpl.queryMessage(topic, key, maxNum, begin, end); + } + + + @Override + public void start() throws MQClientException { + defaultMQAdminExtImpl.start(); + } + + + @Override + public void shutdown() { + defaultMQAdminExtImpl.shutdown(); + } + + + @Override + public void createAndUpdateTopicConfig(String addr, TopicConfig config) throws RemotingException, + MQBrokerException, InterruptedException, MQClientException { + defaultMQAdminExtImpl.createAndUpdateTopicConfig(addr, config); + } + + + @Override + public void createAndUpdateSubscriptionGroupConfig(String addr, SubscriptionGroupConfig config) + throws RemotingException, MQBrokerException, InterruptedException, MQClientException { + defaultMQAdminExtImpl.createAndUpdateSubscriptionGroupConfig(addr, config); + } + + + @Override + public SubscriptionGroupConfig examineSubscriptionGroupConfig(String addr, String group) { + return defaultMQAdminExtImpl.examineSubscriptionGroupConfig(addr, group); + } + + + @Override + public TopicConfig examineTopicConfig(String addr, String topic) { + return defaultMQAdminExtImpl.examineTopicConfig(addr, topic); + } + + + @Override + public TopicStatsTable examineTopicStats(String topic) throws RemotingException, MQClientException, + InterruptedException, MQBrokerException { + return defaultMQAdminExtImpl.examineTopicStats(topic); + } + + + @Override + public ConsumeStats examineConsumeStats(String consumerGroup) throws RemotingException, + MQClientException, InterruptedException, MQBrokerException { + return defaultMQAdminExtImpl.examineConsumeStats(consumerGroup); + } + + + @Override + public ClusterInfo examineBrokerClusterInfo() throws InterruptedException, RemotingConnectException, + RemotingTimeoutException, RemotingSendRequestException, MQBrokerException { + return defaultMQAdminExtImpl.examineBrokerClusterInfo(); + } + + + @Override + public TopicRouteData examineTopicRouteInfo(String topic) throws RemotingException, MQClientException, + InterruptedException { + return defaultMQAdminExtImpl.examineTopicRouteInfo(topic); + } + + + @Override + public void putKVConfig(String namespace, String key, String value) { + defaultMQAdminExtImpl.putKVConfig(namespace, key, value); + } + + + @Override + public String getKVConfig(String namespace, String key) { + return defaultMQAdminExtImpl.getKVConfig(namespace, key); + } + + + @Override + public ConsumerConnection examineConsumerConnectionInfo(String consumerGroup) + throws InterruptedException, MQBrokerException, RemotingException, MQClientException { + return defaultMQAdminExtImpl.examineConsumerConnectionInfo(consumerGroup); + } + + + @Override + public ProducerConnection examineProducerConnectionInfo(String producerGroup, final String topic) + throws RemotingException, MQClientException, InterruptedException, MQBrokerException { + return defaultMQAdminExtImpl.examineProducerConnectionInfo(producerGroup, topic); + } + + + @Override + public int wipeWritePermOfBroker(final String namesrvAddr, String brokerName) + throws RemotingCommandException, RemotingConnectException, RemotingSendRequestException, + RemotingTimeoutException, InterruptedException, MQClientException { + return defaultMQAdminExtImpl.wipeWritePermOfBroker(namesrvAddr, brokerName); + } + + + public String getAdminExtGroup() { + return adminExtGroup; + } + + + public void setAdminExtGroup(String adminExtGroup) { + this.adminExtGroup = adminExtGroup; + } + + + public String getCreateTopicKey() { + return createTopicKey; + } + + + public void setCreateTopicKey(String createTopicKey) { + this.createTopicKey = createTopicKey; + } + + + @Override + public List getNameServerAddressList() { + return this.defaultMQAdminExtImpl.getNameServerAddressList(); + } + + + @Override + public ConsumeByWho whoConsumeTheMessage(String msgId) { + return this.defaultMQAdminExtImpl.whoConsumeTheMessage(msgId); + } + + + @Override + public TopicList fetchAllTopicList() throws RemotingException, MQClientException, InterruptedException { + return this.defaultMQAdminExtImpl.fetchAllTopicList(); + } + + + @Override + public KVTable fetchBrokerRuntimeStats(final String brokerAddr) throws RemotingConnectException, + RemotingSendRequestException, RemotingTimeoutException, InterruptedException, MQBrokerException { + return this.defaultMQAdminExtImpl.fetchBrokerRuntimeStats(brokerAddr); + } + + + @Override + public void deleteTopicInBroker(Set addrs, String topic) throws RemotingException, + MQBrokerException, InterruptedException, MQClientException { + defaultMQAdminExtImpl.deleteTopicInBroker(addrs, topic); + } + + + @Override + public void deleteTopicInNameServer(Set addrs, String topic) throws RemotingException, + MQBrokerException, InterruptedException, MQClientException { + defaultMQAdminExtImpl.deleteTopicInNameServer(addrs, topic); + } + + + @Override + public void deleteSubscriptionGroup(String addr, String groupName) throws RemotingException, + MQBrokerException, InterruptedException, MQClientException { + defaultMQAdminExtImpl.deleteSubscriptionGroup(addr, groupName); + } + + + @Override + public void createAndUpdateKvConfig(String namespace, String key, String value) throws RemotingException, + MQBrokerException, InterruptedException, MQClientException { + defaultMQAdminExtImpl.createAndUpdateKvConfig(namespace, key, value); + } + + + @Override + public void deleteKvConfig(String namespace, String key) throws RemotingException, MQBrokerException, + InterruptedException, MQClientException { + defaultMQAdminExtImpl.deleteKvConfig(namespace, key); + } + + + @Override + public String getProjectGroupByIp(String ip) throws RemotingException, MQBrokerException, + InterruptedException, MQClientException { + return defaultMQAdminExtImpl.getProjectGroupByIp(ip); + } + + + @Override + public String getIpsByProjectGroup(String projectGroup) throws RemotingException, MQBrokerException, + InterruptedException, MQClientException { + return defaultMQAdminExtImpl.getIpsByProjectGroup(projectGroup); + } + + + @Override + public void deleteIpsByProjectGroup(String projectGroup) throws RemotingException, MQBrokerException, + InterruptedException, MQClientException { + defaultMQAdminExtImpl.deleteIpsByProjectGroup(projectGroup); + } + + + public List resetOffsetByTimestampOld(String consumerGroup, String topic, long timestamp, + boolean force) throws RemotingException, MQBrokerException, InterruptedException, + MQClientException { + return defaultMQAdminExtImpl.resetOffsetByTimestampOld(consumerGroup, topic, timestamp, force); + } + + + @Override + public KVTable getKVListByNamespace(String namespace) throws RemotingException, MQClientException, + InterruptedException { + return defaultMQAdminExtImpl.getKVListByNamespace(namespace); + } + + + @Override + public void updateBrokerConfig(String brokerAddr, Properties properties) throws RemotingConnectException, + RemotingSendRequestException, RemotingTimeoutException, UnsupportedEncodingException, + InterruptedException, MQBrokerException { + defaultMQAdminExtImpl.updateBrokerConfig(brokerAddr, properties); + } + + + @Override + public Map resetOffsetByTimestamp(String topic, String group, long timestamp, + boolean isForce) throws RemotingException, MQBrokerException, InterruptedException, + MQClientException { + return defaultMQAdminExtImpl.resetOffsetByTimestamp(topic, group, timestamp, isForce); + } + + + @Override + public Map> getConsumeStatus(String topic, String group, String clientAddr) + throws RemotingException, MQBrokerException, InterruptedException, MQClientException { + return defaultMQAdminExtImpl.getConsumeStatus(topic, group, clientAddr); + } +} diff --git a/rocketmq-tools/src/main/java/com/alibaba/rocketmq/tools/admin/DefaultMQAdminExtImpl.java b/rocketmq-tools/src/main/java/com/alibaba/rocketmq/tools/admin/DefaultMQAdminExtImpl.java new file mode 100644 index 00000000..43108ed3 --- /dev/null +++ b/rocketmq-tools/src/main/java/com/alibaba/rocketmq/tools/admin/DefaultMQAdminExtImpl.java @@ -0,0 +1,536 @@ +/** + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.rocketmq.tools.admin; + +import java.io.UnsupportedEncodingException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.Set; + +import org.slf4j.Logger; + +import com.alibaba.rocketmq.client.QueryResult; +import com.alibaba.rocketmq.client.admin.MQAdminExtInner; +import com.alibaba.rocketmq.client.exception.MQBrokerException; +import com.alibaba.rocketmq.client.exception.MQClientException; +import com.alibaba.rocketmq.client.impl.MQClientManager; +import com.alibaba.rocketmq.client.impl.factory.MQClientFactory; +import com.alibaba.rocketmq.client.log.ClientLogger; +import com.alibaba.rocketmq.common.MixAll; +import com.alibaba.rocketmq.common.ServiceState; +import com.alibaba.rocketmq.common.TopicConfig; +import com.alibaba.rocketmq.common.admin.ConsumeStats; +import com.alibaba.rocketmq.common.admin.OffsetWrapper; +import com.alibaba.rocketmq.common.admin.RollbackStats; +import com.alibaba.rocketmq.common.admin.TopicStatsTable; +import com.alibaba.rocketmq.common.help.FAQUrl; +import com.alibaba.rocketmq.common.message.MessageExt; +import com.alibaba.rocketmq.common.message.MessageQueue; +import com.alibaba.rocketmq.common.namesrv.NamesrvUtil; +import com.alibaba.rocketmq.common.protocol.body.ClusterInfo; +import com.alibaba.rocketmq.common.protocol.body.ConsumeByWho; +import com.alibaba.rocketmq.common.protocol.body.ConsumerConnection; +import com.alibaba.rocketmq.common.protocol.body.KVTable; +import com.alibaba.rocketmq.common.protocol.body.ProducerConnection; +import com.alibaba.rocketmq.common.protocol.body.TopicList; +import com.alibaba.rocketmq.common.protocol.header.UpdateConsumerOffsetRequestHeader; +import com.alibaba.rocketmq.common.protocol.route.BrokerData; +import com.alibaba.rocketmq.common.protocol.route.TopicRouteData; +import com.alibaba.rocketmq.common.subscription.SubscriptionGroupConfig; +import com.alibaba.rocketmq.remoting.exception.RemotingCommandException; +import com.alibaba.rocketmq.remoting.exception.RemotingConnectException; +import com.alibaba.rocketmq.remoting.exception.RemotingException; +import com.alibaba.rocketmq.remoting.exception.RemotingSendRequestException; +import com.alibaba.rocketmq.remoting.exception.RemotingTimeoutException; + + +/** + * 所有运维接口都在这里实现 + * + * @author shijia.wxr + * @since 2013-7-21 + */ +public class DefaultMQAdminExtImpl implements MQAdminExt, MQAdminExtInner { + private final Logger log = ClientLogger.getLog(); + private final DefaultMQAdminExt defaultMQAdminExt; + private ServiceState serviceState = ServiceState.CREATE_JUST; + private MQClientFactory mQClientFactory; + + + public DefaultMQAdminExtImpl(DefaultMQAdminExt defaultMQAdminExt) { + this.defaultMQAdminExt = defaultMQAdminExt; + } + + + @Override + public void start() throws MQClientException { + switch (this.serviceState) { + case CREATE_JUST: + this.serviceState = ServiceState.START_FAILED; + + this.mQClientFactory = + MQClientManager.getInstance().getAndCreateMQClientFactory(this.defaultMQAdminExt); + + boolean registerOK = + mQClientFactory.registerAdminExt(this.defaultMQAdminExt.getAdminExtGroup(), this); + if (!registerOK) { + this.serviceState = ServiceState.CREATE_JUST; + throw new MQClientException("The adminExt group[" + this.defaultMQAdminExt.getAdminExtGroup() + + "] has created already, specifed another name please."// + + FAQUrl.suggestTodo(FAQUrl.GROUP_NAME_DUPLICATE_URL), null); + } + + mQClientFactory.start(); + + log.info("the adminExt [{}] start OK", this.defaultMQAdminExt.getAdminExtGroup()); + + this.serviceState = ServiceState.RUNNING; + break; + case RUNNING: + case START_FAILED: + case SHUTDOWN_ALREADY: + throw new MQClientException("The AdminExt service state not OK, maybe started once, "// + + this.serviceState// + + FAQUrl.suggestTodo(FAQUrl.CLIENT_SERVICE_NOT_OK), null); + default: + break; + } + } + + + @Override + public void shutdown() { + switch (this.serviceState) { + case CREATE_JUST: + break; + case RUNNING: + this.mQClientFactory.unregisterAdminExt(this.defaultMQAdminExt.getAdminExtGroup()); + this.mQClientFactory.shutdown(); + + log.info("the adminExt [{}] shutdown OK", this.defaultMQAdminExt.getAdminExtGroup()); + this.serviceState = ServiceState.SHUTDOWN_ALREADY; + break; + case SHUTDOWN_ALREADY: + break; + default: + break; + } + } + + + @Override + public void createAndUpdateTopicConfig(String addr, TopicConfig config) throws RemotingException, + MQBrokerException, InterruptedException, MQClientException { + this.mQClientFactory.getMQClientAPIImpl().createTopic(addr, + this.defaultMQAdminExt.getCreateTopicKey(), config, 3000); + } + + + @Override + public void createAndUpdateSubscriptionGroupConfig(String addr, SubscriptionGroupConfig config) + throws RemotingException, MQBrokerException, InterruptedException, MQClientException { + this.mQClientFactory.getMQClientAPIImpl().createSubscriptionGroup(addr, config, 3000); + } + + + @Override + public SubscriptionGroupConfig examineSubscriptionGroupConfig(String addr, String group) { + // TODO Auto-generated method stub + return null; + } + + + @Override + public TopicConfig examineTopicConfig(String addr, String topic) { + // TODO Auto-generated method stub + return null; + } + + + @Override + public TopicStatsTable examineTopicStats(String topic) throws RemotingException, MQClientException, + InterruptedException, MQBrokerException { + TopicRouteData topicRouteData = this.examineTopicRouteInfo(topic); + TopicStatsTable topicStatsTable = new TopicStatsTable(); + + for (BrokerData bd : topicRouteData.getBrokerDatas()) { + String addr = bd.selectBrokerAddr(); + if (addr != null) { + TopicStatsTable tst = + this.mQClientFactory.getMQClientAPIImpl().getTopicStatsInfo(addr, topic, 3000); + topicStatsTable.getOffsetTable().putAll(tst.getOffsetTable()); + } + } + + if (topicStatsTable.getOffsetTable().isEmpty()) { + throw new MQClientException("Not found the topic stats info", null); + } + + return topicStatsTable; + } + + + @Override + public ConsumeStats examineConsumeStats(String consumerGroup) throws RemotingException, + MQClientException, InterruptedException, MQBrokerException { + String retryTopic = MixAll.getRetryTopic(consumerGroup); + TopicRouteData topicRouteData = this.examineTopicRouteInfo(retryTopic); + ConsumeStats result = new ConsumeStats(); + + for (BrokerData bd : topicRouteData.getBrokerDatas()) { + String addr = bd.selectBrokerAddr(); + if (addr != null) { + // 由于查询时间戳会产生IO操作,可能会耗时较长,所以超时时间设置为15s + ConsumeStats consumeStats = + this.mQClientFactory.getMQClientAPIImpl().getConsumeStats(addr, consumerGroup, 15000); + result.getOffsetTable().putAll(consumeStats.getOffsetTable()); + long value = result.getConsumeTps() + consumeStats.getConsumeTps(); + result.setConsumeTps(value); + } + } + + if (result.getOffsetTable().isEmpty()) { + throw new MQClientException( + "Not found the consumer group consume stats, because return offset table is empty, maybe the consumer not consume any message", + null); + } + + return result; + } + + + @Override + public ClusterInfo examineBrokerClusterInfo() throws InterruptedException, MQBrokerException, + RemotingTimeoutException, RemotingSendRequestException, RemotingConnectException { + return this.mQClientFactory.getMQClientAPIImpl().getBrokerClusterInfo(3000); + } + + + @Override + public TopicRouteData examineTopicRouteInfo(String topic) throws RemotingException, MQClientException, + InterruptedException { + return this.mQClientFactory.getMQClientAPIImpl().getTopicRouteInfoFromNameServer(topic, 3000); + } + + + @Override + public void putKVConfig(String namespace, String key, String value) { + // TODO Auto-generated method stub + + } + + + @Override + public String getKVConfig(String namespace, String key) { + // TODO Auto-generated method stub + return null; + } + + + @Override + public void createTopic(String key, String newTopic, int queueNum) throws MQClientException { + this.mQClientFactory.getMQAdminImpl().createTopic(key, newTopic, queueNum); + } + + + @Override + public long searchOffset(MessageQueue mq, long timestamp) throws MQClientException { + return this.mQClientFactory.getMQAdminImpl().searchOffset(mq, timestamp); + } + + + @Override + public long maxOffset(MessageQueue mq) throws MQClientException { + return this.mQClientFactory.getMQAdminImpl().maxOffset(mq); + } + + + @Override + public long minOffset(MessageQueue mq) throws MQClientException { + return this.mQClientFactory.getMQAdminImpl().minOffset(mq); + } + + + @Override + public long earliestMsgStoreTime(MessageQueue mq) throws MQClientException { + return this.mQClientFactory.getMQAdminImpl().earliestMsgStoreTime(mq); + } + + + @Override + public MessageExt viewMessage(String msgId) throws RemotingException, MQBrokerException, + InterruptedException, MQClientException { + return this.mQClientFactory.getMQAdminImpl().viewMessage(msgId); + } + + + @Override + public QueryResult queryMessage(String topic, String key, int maxNum, long begin, long end) + throws MQClientException, InterruptedException { + return this.mQClientFactory.getMQAdminImpl().queryMessage(topic, key, maxNum, begin, end); + } + + + @Override + public ConsumerConnection examineConsumerConnectionInfo(String consumerGroup) + throws InterruptedException, MQBrokerException, RemotingException, MQClientException { + String topic = MixAll.getRetryTopic(consumerGroup); + TopicRouteData topicRouteData = this.examineTopicRouteInfo(topic); + ConsumerConnection result = new ConsumerConnection(); + + for (BrokerData bd : topicRouteData.getBrokerDatas()) { + String addr = bd.selectBrokerAddr(); + if (addr != null) { + return this.mQClientFactory.getMQClientAPIImpl().getConsumerConnectionList(addr, + consumerGroup, 3000); + } + } + + if (result.getConnectionSet().isEmpty()) { + throw new MQClientException("Not found the consumer group connection", null); + } + + return result; + } + + + @Override + public ProducerConnection examineProducerConnectionInfo(String producerGroup, final String topic) + throws RemotingException, MQClientException, InterruptedException, MQBrokerException { + TopicRouteData topicRouteData = this.examineTopicRouteInfo(topic); + ProducerConnection result = new ProducerConnection(); + + for (BrokerData bd : topicRouteData.getBrokerDatas()) { + String addr = bd.selectBrokerAddr(); + if (addr != null) { + return this.mQClientFactory.getMQClientAPIImpl().getProducerConnectionList(addr, + producerGroup, 300); + } + } + + if (result.getConnectionSet().isEmpty()) { + throw new MQClientException("Not found the consumer group connection", null); + } + + return result; + } + + + @Override + public int wipeWritePermOfBroker(final String namesrvAddr, String brokerName) + throws RemotingCommandException, RemotingConnectException, RemotingSendRequestException, + RemotingTimeoutException, InterruptedException, MQClientException { + return this.mQClientFactory.getMQClientAPIImpl().wipeWritePermOfBroker(namesrvAddr, brokerName, 3000); + } + + + @Override + public List getNameServerAddressList() { + return this.mQClientFactory.getMQClientAPIImpl().getNameServerAddressList(); + } + + + @Override + public ConsumeByWho whoConsumeTheMessage(String msgId) { + // TODO Auto-generated method stub + return null; + } + + + @Override + public TopicList fetchAllTopicList() throws RemotingException, MQClientException, InterruptedException { + return this.mQClientFactory.getMQClientAPIImpl().getTopicListFromNameServer(3000); + } + + + @Override + public KVTable fetchBrokerRuntimeStats(final String brokerAddr) throws RemotingConnectException, + RemotingSendRequestException, RemotingTimeoutException, InterruptedException, MQBrokerException { + return this.mQClientFactory.getMQClientAPIImpl().getBrokerRuntimeInfo(brokerAddr, 3000); + } + + + @Override + public void deleteTopicInBroker(Set addrs, String topic) throws RemotingException, + MQBrokerException, InterruptedException, MQClientException { + for (String addr : addrs) { + this.mQClientFactory.getMQClientAPIImpl().deleteTopicInBroker(addr, topic, 3000); + } + } + + + @Override + public void deleteTopicInNameServer(Set addrs, String topic) throws RemotingException, + MQBrokerException, InterruptedException, MQClientException { + if (addrs == null) { + String ns = this.mQClientFactory.getMQClientAPIImpl().fetchNameServerAddr(); + addrs = new HashSet(Arrays.asList(ns.split(";"))); + } + for (String addr : addrs) { + this.mQClientFactory.getMQClientAPIImpl().deleteTopicInNameServer(addr, topic, 3000); + } + } + + + @Override + public void deleteSubscriptionGroup(String addr, String groupName) throws RemotingException, + MQBrokerException, InterruptedException, MQClientException { + this.mQClientFactory.getMQClientAPIImpl().deleteSubscriptionGroup(addr, groupName, 3000); + } + + + @Override + public void createAndUpdateKvConfig(String namespace, String key, String value) throws RemotingException, + MQBrokerException, InterruptedException, MQClientException { + this.mQClientFactory.getMQClientAPIImpl().putKVConfigValue(namespace, key, value, 3000); + } + + + @Override + public void deleteKvConfig(String namespace, String key) throws RemotingException, MQBrokerException, + InterruptedException, MQClientException { + this.mQClientFactory.getMQClientAPIImpl().deleteKVConfigValue(namespace, key, 3000); + } + + + @Override + public String getProjectGroupByIp(String ip) throws RemotingException, MQBrokerException, + InterruptedException, MQClientException { + return this.mQClientFactory.getMQClientAPIImpl().getProjectGroupByIp(ip, 3000); + } + + + @Override + public String getIpsByProjectGroup(String projectGroup) throws RemotingException, MQBrokerException, + InterruptedException, MQClientException { + String namespace = NamesrvUtil.NAMESPACE_PROJECT_CONFIG; + return this.mQClientFactory.getMQClientAPIImpl().getKVConfigByValue(namespace, projectGroup, 3000); + } + + + @Override + public void deleteIpsByProjectGroup(String projectGroup) throws RemotingException, MQBrokerException, + InterruptedException, MQClientException { + String namespace = NamesrvUtil.NAMESPACE_PROJECT_CONFIG; + this.mQClientFactory.getMQClientAPIImpl().deleteKVConfigByValue(namespace, projectGroup, 3000); + } + + + @Override + public List resetOffsetByTimestampOld(String consumerGroup, String topic, long timestamp, + boolean force) throws RemotingException, MQBrokerException, InterruptedException, + MQClientException { + TopicRouteData topicRouteData = this.examineTopicRouteInfo(topic); + List rollbackStatsList = new ArrayList(); + for (BrokerData bd : topicRouteData.getBrokerDatas()) { + String addr = bd.selectBrokerAddr(); + if (addr != null) { + // 根据 consumerGroup 查找对应的 mq + ConsumeStats consumeStats = + this.mQClientFactory.getMQClientAPIImpl().getConsumeStats(addr, consumerGroup, 3000); + + // 根据 topic 过滤不需要的 mq + for (Map.Entry entry : consumeStats.getOffsetTable().entrySet()) { + MessageQueue queue = entry.getKey(); + OffsetWrapper offsetWrapper = entry.getValue(); + if (topic.equals(queue.getTopic())) { + // 根据 timestamp 查找对应的offset + long offset = + this.mQClientFactory.getMQClientAPIImpl().searchOffset(addr, topic, + queue.getQueueId(), timestamp, 3000); + // 构建按时间回溯消费进度 + RollbackStats rollbackStats = new RollbackStats(); + rollbackStats.setBrokerName(bd.getBrokerName()); + rollbackStats.setQueueId(queue.getQueueId()); + rollbackStats.setBrokerOffset(offsetWrapper.getBrokerOffset()); + rollbackStats.setConsumerOffset(offsetWrapper.getConsumerOffset()); + rollbackStats.setTimestampOffset(offset); + rollbackStats.setRollbackOffset(offsetWrapper.getConsumerOffset()); + // 更新 offset + if (force || offset <= offsetWrapper.getConsumerOffset()) { + rollbackStats.setRollbackOffset(offset); + UpdateConsumerOffsetRequestHeader requestHeader = + new UpdateConsumerOffsetRequestHeader(); + requestHeader.setConsumerGroup(consumerGroup); + requestHeader.setTopic(topic); + requestHeader.setQueueId(queue.getQueueId()); + requestHeader.setCommitOffset(offset); + this.mQClientFactory.getMQClientAPIImpl().updateConsumerOffset(addr, + requestHeader, 3000); + } + rollbackStatsList.add(rollbackStats); + } + } + } + } + return rollbackStatsList; + } + + + @Override + public KVTable getKVListByNamespace(String namespace) throws RemotingException, MQClientException, + InterruptedException { + return this.mQClientFactory.getMQClientAPIImpl().getKVListByNamespace(namespace, 5000); + } + + + @Override + public void updateBrokerConfig(String brokerAddr, Properties properties) throws RemotingConnectException, + RemotingSendRequestException, RemotingTimeoutException, UnsupportedEncodingException, + InterruptedException, MQBrokerException { + this.mQClientFactory.getMQClientAPIImpl().updateBrokerConfig(brokerAddr, properties, 5000); + } + + + @Override + public Map resetOffsetByTimestamp(String topic, String group, long timestamp, + boolean isForce) throws RemotingException, MQBrokerException, InterruptedException, + MQClientException { + TopicRouteData topicRouteData = this.examineTopicRouteInfo(topic); + List brokerDatas = topicRouteData.getBrokerDatas(); + // 每个 broker 上有所有的 consumer 连接,故只需要在一个 broker 执行即可。 + if (brokerDatas != null && brokerDatas.size() > 0) { + String addr = brokerDatas.get(0).selectBrokerAddr(); + if (addr != null) { + return this.mQClientFactory.getMQClientAPIImpl().invokeBrokerToResetOffset(addr, topic, + group, timestamp, isForce, 5000); + } + } + return Collections.EMPTY_MAP; + } + + + @Override + public Map> getConsumeStatus(String topic, String group, String clientAddr) + throws RemotingException, MQBrokerException, InterruptedException, MQClientException { + TopicRouteData topicRouteData = this.examineTopicRouteInfo(topic); + List brokerDatas = topicRouteData.getBrokerDatas(); + // 每个 broker 上有所有的 consumer 连接,故只需要在一个 broker 执行即可。 + if (brokerDatas != null && brokerDatas.size() > 0) { + String addr = brokerDatas.get(0).selectBrokerAddr(); + if (addr != null) { + return this.mQClientFactory.getMQClientAPIImpl().invokeBrokerToGetConsumerStatus(addr, topic, + group, clientAddr, 5000); + } + } + return Collections.EMPTY_MAP; + } +} diff --git a/rocketmq-tools/src/main/java/com/alibaba/rocketmq/tools/admin/MQAdminExt.java b/rocketmq-tools/src/main/java/com/alibaba/rocketmq/tools/admin/MQAdminExt.java new file mode 100644 index 00000000..94c3ba36 --- /dev/null +++ b/rocketmq-tools/src/main/java/com/alibaba/rocketmq/tools/admin/MQAdminExt.java @@ -0,0 +1,456 @@ +/** + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.rocketmq.tools.admin; + +import java.io.UnsupportedEncodingException; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.Set; + +import com.alibaba.rocketmq.client.MQAdmin; +import com.alibaba.rocketmq.client.exception.MQBrokerException; +import com.alibaba.rocketmq.client.exception.MQClientException; +import com.alibaba.rocketmq.common.TopicConfig; +import com.alibaba.rocketmq.common.admin.ConsumeStats; +import com.alibaba.rocketmq.common.admin.RollbackStats; +import com.alibaba.rocketmq.common.admin.TopicStatsTable; +import com.alibaba.rocketmq.common.message.MessageQueue; +import com.alibaba.rocketmq.common.protocol.body.ClusterInfo; +import com.alibaba.rocketmq.common.protocol.body.ConsumeByWho; +import com.alibaba.rocketmq.common.protocol.body.ConsumerConnection; +import com.alibaba.rocketmq.common.protocol.body.KVTable; +import com.alibaba.rocketmq.common.protocol.body.ProducerConnection; +import com.alibaba.rocketmq.common.protocol.body.TopicList; +import com.alibaba.rocketmq.common.protocol.route.TopicRouteData; +import com.alibaba.rocketmq.common.subscription.SubscriptionGroupConfig; +import com.alibaba.rocketmq.remoting.exception.RemotingCommandException; +import com.alibaba.rocketmq.remoting.exception.RemotingConnectException; +import com.alibaba.rocketmq.remoting.exception.RemotingException; +import com.alibaba.rocketmq.remoting.exception.RemotingSendRequestException; +import com.alibaba.rocketmq.remoting.exception.RemotingTimeoutException; + + +/** + * MQ管理类接口,涉及所有与MQ管理相关的对外接口
+ * 包括Topic创建、订阅组创建、配置修改等 + * + * @since 2013-7-14 + */ +public interface MQAdminExt extends MQAdmin { + public void start() throws MQClientException; + + + public void shutdown(); + + + /** + * 更新Broker配置 + * + * @param brokerAddr + * @param properties + * @throws MQBrokerException + * @throws InterruptedException + * @throws UnsupportedEncodingException + * @throws RemotingTimeoutException + * @throws RemotingSendRequestException + * @throws RemotingConnectException + */ + public void updateBrokerConfig(final String brokerAddr, final Properties properties) + throws RemotingConnectException, RemotingSendRequestException, RemotingTimeoutException, + UnsupportedEncodingException, InterruptedException, MQBrokerException; + + + /** + * 向指定Broker创建或者更新Topic配置 + * + * @param addr + * @param config + * @throws MQClientException + * @throws InterruptedException + * @throws MQBrokerException + * @throws RemotingException + */ + public void createAndUpdateTopicConfig(final String addr, final TopicConfig config) + throws RemotingException, MQBrokerException, InterruptedException, MQClientException; + + + /** + * 向指定Broker创建或者更新订阅组配置 + * + * @param addr + * @param config + * @throws MQClientException + * @throws InterruptedException + * @throws MQBrokerException + * @throws RemotingException + */ + public void createAndUpdateSubscriptionGroupConfig(final String addr, final SubscriptionGroupConfig config) + throws RemotingException, MQBrokerException, InterruptedException, MQClientException; + + + /** + * 查询指定Broker的订阅组配置 + * + * @param addr + * @param group + * @return + */ + public SubscriptionGroupConfig examineSubscriptionGroupConfig(final String addr, final String group); + + + /** + * 查询指定Broker的Topic配置 + * + * @param addr + * @param topic + * @return + */ + public TopicConfig examineTopicConfig(final String addr, final String topic); + + + /** + * 查询Topic Offset信息 + * + * @param topic + * @return + */ + public TopicStatsTable examineTopicStats(final String topic) throws RemotingException, MQClientException, + InterruptedException, MQBrokerException; + + + /** + * 从Name Server获取所有Topic列表 + * + * @return + * @throws InterruptedException + * @throws MQClientException + * @throws RemotingException + */ + public TopicList fetchAllTopicList() throws RemotingException, MQClientException, InterruptedException; + + + /** + * 获取Broker运行时数据 + * + * @return + * @throws MQBrokerException + * @throws InterruptedException + * @throws RemotingTimeoutException + * @throws RemotingSendRequestException + * @throws RemotingConnectException + */ + public KVTable fetchBrokerRuntimeStats(final String brokerAddr) throws RemotingConnectException, + RemotingSendRequestException, RemotingTimeoutException, InterruptedException, MQBrokerException; + + + /** + * 查询消费进度 + * + * @param consumerGroup + * @return + * @throws InterruptedException + * @throws MQClientException + * @throws RemotingException + * @throws MQBrokerException + */ + public ConsumeStats examineConsumeStats(final String consumerGroup) throws RemotingException, + MQClientException, InterruptedException, MQBrokerException; + + + /** + * 查看集群信息 + * + * @return + */ + public ClusterInfo examineBrokerClusterInfo() throws InterruptedException, MQBrokerException, + RemotingTimeoutException, RemotingSendRequestException, RemotingConnectException; + + + /** + * 查看Topic路由信息 + * + * @param topic + * @return + */ + public TopicRouteData examineTopicRouteInfo(final String topic) throws RemotingException, + MQClientException, InterruptedException; + + + /** + * 查看Consumer网络连接、订阅关系 + * + * @param consumerGroup + * @return + * @throws MQBrokerException + * @throws InterruptedException + * @throws RemotingTimeoutException + * @throws RemotingSendRequestException + * @throws RemotingConnectException + * @throws MQClientException + * @throws RemotingException + */ + public ConsumerConnection examineConsumerConnectionInfo(final String consumerGroup) + throws RemotingConnectException, RemotingSendRequestException, RemotingTimeoutException, + InterruptedException, MQBrokerException, RemotingException, MQClientException; + + + /** + * 查看Producer网络连接 + * + * @param producerGroup + * @param topic + * @return + * @throws InterruptedException + * @throws MQClientException + * @throws RemotingException + * @throws MQBrokerException + */ + public ProducerConnection examineProducerConnectionInfo(final String producerGroup, final String topic) + throws RemotingException, MQClientException, InterruptedException, MQBrokerException; + + + /** + * 获取Name Server地址列表 + * + * @return + */ + public List getNameServerAddressList(); + + + /** + * 清除某个Broker的写权限,针对所有Name Server + * + * @param brokerName + * @return 返回清除了多少个topic + * @throws MQClientException + * @throws InterruptedException + * @throws RemotingTimeoutException + * @throws RemotingSendRequestException + * @throws RemotingConnectException + * @throws RemotingCommandException + */ + public int wipeWritePermOfBroker(final String namesrvAddr, String brokerName) + throws RemotingCommandException, RemotingConnectException, RemotingSendRequestException, + RemotingTimeoutException, InterruptedException, MQClientException; + + + /** + * 查看某个订阅组被谁消费了 + * + * @param msgId + * @return + */ + public ConsumeByWho whoConsumeTheMessage(final String msgId); + + + /** + * 向Name Server增加一个配置项 + * + * @param namespace + * @param key + * @param value + */ + public void putKVConfig(final String namespace, final String key, final String value); + + + /** + * 从Name Server获取一个配置项 + * + * @param namespace + * @param key + * @return + */ + public String getKVConfig(final String namespace, final String key); + + + /** + * 获取指定Namespace下的所有kv + * + * @param namespace + * @return + * @throws InterruptedException + * @throws MQClientException + * @throws RemotingException + */ + public KVTable getKVListByNamespace(final String namespace) throws RemotingException, MQClientException, + InterruptedException; + + + /** + * 删除 broker 上的 topic 信息 + * + * @param addrs + * @param topic + * @throws RemotingException + * @throws MQBrokerException + * @throws InterruptedException + * @throws MQClientException + */ + public void deleteTopicInBroker(final Set addrs, final String topic) throws RemotingException, + MQBrokerException, InterruptedException, MQClientException; + + + /** + * 删除 broker 上的 topic 信息 + * + * @param addrs + * @param topic + * @throws RemotingException + * @throws MQBrokerException + * @throws InterruptedException + * @throws MQClientException + */ + public void deleteTopicInNameServer(final Set addrs, final String topic) + throws RemotingException, MQBrokerException, InterruptedException, MQClientException; + + + /** + * 删除 broker 上的 subscription group 信息 + * + * @param addr + * @param groupName + * @throws RemotingException + * @throws MQBrokerException + * @throws InterruptedException + * @throws MQClientException + */ + public void deleteSubscriptionGroup(final String addr, String groupName) throws RemotingException, + MQBrokerException, InterruptedException, MQClientException; + + + /** + * 在 namespace 上添加或者更新 KV 配置 + * + * @param namespace + * @param key + * @param value + * @throws RemotingException + * @throws MQBrokerException + * @throws InterruptedException + * @throws MQClientException + */ + public void createAndUpdateKvConfig(String namespace, String key, String value) throws RemotingException, + MQBrokerException, InterruptedException, MQClientException; + + + /** + * 删除 namespace 上的 KV 配置 + * + * @param namespace + * @param key + * @throws RemotingException + * @throws MQBrokerException + * @throws InterruptedException + * @throws MQClientException + */ + public void deleteKvConfig(String namespace, String key) throws RemotingException, MQBrokerException, + InterruptedException, MQClientException; + + + /** + * 通过 server ip 获取 project 信息 + * + * @param ip + * @throws RemotingException + * @throws MQBrokerException + * @throws InterruptedException + * @throws MQClientException + * @return + */ + public String getProjectGroupByIp(String ip) throws RemotingException, MQBrokerException, + InterruptedException, MQClientException; + + + /** + * 通过 project 获取所有的 server ip 信息 + * + * @param projectGroup + * @throws RemotingException + * @throws MQBrokerException + * @throws InterruptedException + * @throws MQClientException + * @return + */ + public String getIpsByProjectGroup(String projectGroup) throws RemotingException, MQBrokerException, + InterruptedException, MQClientException; + + + /** + * 删除 project group 对应的所有 server ip + * + * @param key + * @throws RemotingException + * @throws MQBrokerException + * @throws InterruptedException + * @throws MQClientException + */ + public void deleteIpsByProjectGroup(String key) throws RemotingException, MQBrokerException, + InterruptedException, MQClientException; + + + /** + * 按照时间回溯消费进度(客户端需要重启) + * + * @param consumerGroup + * @param topic + * @param timestamp + * @param force + * @throws RemotingException + * @throws MQBrokerException + * @throws InterruptedException + * @throws MQClientException + * @return + */ + public List resetOffsetByTimestampOld(String consumerGroup, String topic, long timestamp, + boolean force) throws RemotingException, MQBrokerException, InterruptedException, + MQClientException; + + + /** + * 按照时间回溯消费进度(客户端不需要重启) + * + * @param topic + * @param group + * @param timestamp + * @param isForce + * @throws RemotingException + * @throws MQBrokerException + * @throws InterruptedException + * @throws MQClientException + * @return + */ + public Map resetOffsetByTimestamp(String topic, String group, long timestamp, + boolean isForce) throws RemotingException, MQBrokerException, InterruptedException, + MQClientException; + + + /** + * 通过客户端查看消费者的消费情况 + * + * @param topic + * @param group + * @param clientAddr + * @return + * @throws RemotingException + * @throws MQBrokerException + * @throws InterruptedException + * @throws MQClientException + */ + public Map> getConsumeStatus(String topic, String group, String clientAddr) + throws RemotingException, MQBrokerException, InterruptedException, MQClientException; + +} diff --git a/rocketmq-tools/src/main/java/com/alibaba/rocketmq/tools/command/CommandUtil.java b/rocketmq-tools/src/main/java/com/alibaba/rocketmq/tools/command/CommandUtil.java new file mode 100644 index 00000000..704cef02 --- /dev/null +++ b/rocketmq-tools/src/main/java/com/alibaba/rocketmq/tools/command/CommandUtil.java @@ -0,0 +1,66 @@ +/** + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.rocketmq.tools.command; + +import java.util.HashSet; +import java.util.Set; + +import com.alibaba.rocketmq.client.exception.MQBrokerException; +import com.alibaba.rocketmq.common.MixAll; +import com.alibaba.rocketmq.common.protocol.body.ClusterInfo; +import com.alibaba.rocketmq.common.protocol.route.BrokerData; +import com.alibaba.rocketmq.remoting.exception.RemotingConnectException; +import com.alibaba.rocketmq.remoting.exception.RemotingSendRequestException; +import com.alibaba.rocketmq.remoting.exception.RemotingTimeoutException; +import com.alibaba.rocketmq.tools.admin.MQAdminExt; + + +/** + * 各个子命令的接口 + * + * @author shijia.wxr + * @since 2013-7-25 + */ +public class CommandUtil { + public static Set fetchMasterAddrByClusterName(final MQAdminExt adminExt, final String clusterName) + throws InterruptedException, RemotingConnectException, RemotingTimeoutException, + RemotingSendRequestException, MQBrokerException { + Set masterSet = new HashSet(); + + ClusterInfo clusterInfoSerializeWrapper = adminExt.examineBrokerClusterInfo(); + + Set brokerNameSet = clusterInfoSerializeWrapper.getClusterAddrTable().get(clusterName); + + if (brokerNameSet != null) { + for (String brokerName : brokerNameSet) { + BrokerData brokerData = clusterInfoSerializeWrapper.getBrokerAddrTable().get(brokerName); + if (brokerData != null) { + + String addr = brokerData.getBrokerAddrs().get(MixAll.MASTER_ID); + if (addr != null) { + masterSet.add(addr); + } + } + } + } + else { + System.out + .printf("[error] Make sure the specified clusterName exists or the nameserver which connected is correct."); + } + + return masterSet; + } +} diff --git a/rocketmq-tools/src/main/java/com/alibaba/rocketmq/tools/command/MQAdminStartup.java b/rocketmq-tools/src/main/java/com/alibaba/rocketmq/tools/command/MQAdminStartup.java new file mode 100644 index 00000000..1656212f --- /dev/null +++ b/rocketmq-tools/src/main/java/com/alibaba/rocketmq/tools/command/MQAdminStartup.java @@ -0,0 +1,208 @@ +/** + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.rocketmq.tools.command; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.commons.cli.CommandLine; +import org.apache.commons.cli.Options; +import org.apache.commons.cli.PosixParser; +import org.slf4j.LoggerFactory; + +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.classic.joran.JoranConfigurator; +import ch.qos.logback.core.joran.spi.JoranException; + +import com.alibaba.rocketmq.common.MQVersion; +import com.alibaba.rocketmq.common.MixAll; +import com.alibaba.rocketmq.remoting.protocol.RemotingCommand; +import com.alibaba.rocketmq.tools.command.broker.BrokerStatsSubCommand; +import com.alibaba.rocketmq.tools.command.broker.UpdateBrokerConfigSubCommand; +import com.alibaba.rocketmq.tools.command.cluster.ClusterListSubCommand; +import com.alibaba.rocketmq.tools.command.connection.ConsumerConnectionSubCommand; +import com.alibaba.rocketmq.tools.command.connection.ProducerConnectionSubCommand; +import com.alibaba.rocketmq.tools.command.consumer.ConsumerProgressSubCommand; +import com.alibaba.rocketmq.tools.command.consumer.DeleteSubscriptionGroupCommand; +import com.alibaba.rocketmq.tools.command.consumer.UpdateSubGroupSubCommand; +import com.alibaba.rocketmq.tools.command.message.QueryMsgByIdSubCommand; +import com.alibaba.rocketmq.tools.command.message.QueryMsgByKeySubCommand; +import com.alibaba.rocketmq.tools.command.message.QueryMsgByOffsetSubCommand; +import com.alibaba.rocketmq.tools.command.namesrv.DeleteKvConfigCommand; +import com.alibaba.rocketmq.tools.command.namesrv.DeleteProjectGroupCommand; +import com.alibaba.rocketmq.tools.command.namesrv.GetProjectGroupCommand; +import com.alibaba.rocketmq.tools.command.namesrv.UpdateKvConfigCommand; +import com.alibaba.rocketmq.tools.command.namesrv.UpdateProjectGroupCommand; +import com.alibaba.rocketmq.tools.command.namesrv.WipeWritePermSubCommand; +import com.alibaba.rocketmq.tools.command.offset.GetConsumerStatusCommand; +import com.alibaba.rocketmq.tools.command.offset.ResetOffsetByTimeCommand; +import com.alibaba.rocketmq.tools.command.offset.ResetOffsetByTimeOldCommand; +import com.alibaba.rocketmq.tools.command.topic.DeleteTopicSubCommand; +import com.alibaba.rocketmq.tools.command.topic.TopicListSubCommand; +import com.alibaba.rocketmq.tools.command.topic.TopicRouteSubCommand; +import com.alibaba.rocketmq.tools.command.topic.TopicStatsSubCommand; +import com.alibaba.rocketmq.tools.command.topic.UpdateTopicSubCommand; + + +/** + * mqadmin启动程序 + * + * @author shijia.wxr + * @since 2013-7-25 + */ +public class MQAdminStartup { + protected static List subCommandList = new ArrayList(); + static { + subCommandList.add(new UpdateTopicSubCommand()); + subCommandList.add(new DeleteTopicSubCommand()); + subCommandList.add(new UpdateSubGroupSubCommand()); + subCommandList.add(new DeleteSubscriptionGroupCommand()); + subCommandList.add(new UpdateBrokerConfigSubCommand()); + + subCommandList.add(new TopicRouteSubCommand()); + subCommandList.add(new TopicStatsSubCommand()); + + subCommandList.add(new BrokerStatsSubCommand()); + subCommandList.add(new QueryMsgByIdSubCommand()); + subCommandList.add(new QueryMsgByKeySubCommand()); + subCommandList.add(new QueryMsgByOffsetSubCommand()); + + subCommandList.add(new ProducerConnectionSubCommand()); + subCommandList.add(new ConsumerConnectionSubCommand()); + subCommandList.add(new ConsumerProgressSubCommand()); + + subCommandList.add(new ClusterListSubCommand()); + subCommandList.add(new TopicListSubCommand()); + + subCommandList.add(new UpdateKvConfigCommand()); + subCommandList.add(new DeleteKvConfigCommand()); + + subCommandList.add(new UpdateProjectGroupCommand()); + subCommandList.add(new DeleteProjectGroupCommand()); + subCommandList.add(new GetProjectGroupCommand()); + subCommandList.add(new WipeWritePermSubCommand()); + subCommandList.add(new ResetOffsetByTimeOldCommand()); + subCommandList.add(new ResetOffsetByTimeCommand()); + subCommandList.add(new GetConsumerStatusCommand()); + } + + + public static void main(String[] args) { + System.setProperty(RemotingCommand.RemotingVersionKey, Integer.toString(MQVersion.CurrentVersion)); + + try { + initLogback(); + switch (args.length) { + case 0: + printHelp(); + break; + case 2: + if (args[0].equals("help")) { + SubCommand cmd = findSubCommand(args[1]); + if (cmd != null) { + Options options = MixAll.buildCommandlineOptions(new Options()); + options = cmd.buildCommandlineOptions(options); + if (options != null) { + MixAll.printCommandLineHelp("mqadmin " + cmd.commandName(), options); + } + } + else { + System.out.println("The sub command \'" + args[1] + "\' not exist."); + } + break; + } + case 1: + default: + SubCommand cmd = findSubCommand(args[0]); + if (cmd != null) { + // 将main中的args转化为子命令的args(去除第一个参数) + String[] subargs = parseSubArgs(args); + + // 解析命令行 + Options options = MixAll.buildCommandlineOptions(new Options()); + final CommandLine commandLine = + MixAll.parseCmdLine("mqadmin " + cmd.commandName(), subargs, + cmd.buildCommandlineOptions(options), new PosixParser()); + if (null == commandLine) { + System.exit(-1); + return; + } + + if (commandLine.hasOption('n')) { + String namesrvAddr = commandLine.getOptionValue('n'); + System.setProperty(MixAll.NAMESRV_ADDR_PROPERTY, namesrvAddr); + } + + cmd.execute(commandLine, options); + } + else { + System.out.println("The sub command \'" + args[0] + "\' not exist."); + } + break; + } + } + catch (Exception e) { + e.printStackTrace(); + } + } + + + private static void initLogback() throws JoranException { + String rocketmqHome = + System.getProperty(MixAll.ROCKETMQ_HOME_PROPERTY, System.getenv(MixAll.ROCKETMQ_HOME_ENV)); + + // 初始化Logback + LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory(); + JoranConfigurator configurator = new JoranConfigurator(); + configurator.setContext(lc); + lc.reset(); + configurator.doConfigure(rocketmqHome + "/conf/logback_tools.xml"); + } + + + private static String[] parseSubArgs(String[] args) { + if (args.length > 1) { + String[] result = new String[args.length - 1]; + for (int i = 0; i < args.length - 1; i++) { + result[i] = args[i + 1]; + } + return result; + } + return null; + } + + + private static SubCommand findSubCommand(final String name) { + for (SubCommand cmd : subCommandList) { + if (cmd.commandName().toUpperCase().equals(name.toUpperCase())) { + return cmd; + } + } + + return null; + } + + + private static void printHelp() { + System.out.println("The most commonly used mqadmin commands are:"); + + for (SubCommand cmd : subCommandList) { + System.out.printf(" %-20s %s\n", cmd.commandName(), cmd.commandDesc()); + } + + System.out.println("\nSee 'mqadmin help ' for more information on a specific command."); + } +} diff --git a/rocketmq-tools/src/main/java/com/alibaba/rocketmq/tools/command/SubCommand.java b/rocketmq-tools/src/main/java/com/alibaba/rocketmq/tools/command/SubCommand.java new file mode 100644 index 00000000..1b2e3c5b --- /dev/null +++ b/rocketmq-tools/src/main/java/com/alibaba/rocketmq/tools/command/SubCommand.java @@ -0,0 +1,39 @@ +/** + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.rocketmq.tools.command; + +import org.apache.commons.cli.CommandLine; +import org.apache.commons.cli.Options; + + +/** + * 各个子命令的接口 + * + * @author shijia.wxr + * @since 2013-7-25 + */ +public interface SubCommand { + public String commandName(); + + + public String commandDesc(); + + + public Options buildCommandlineOptions(final Options options); + + + public void execute(final CommandLine commandLine, final Options options); +} diff --git a/rocketmq-tools/src/main/java/com/alibaba/rocketmq/tools/command/broker/BrokerStatsSubCommand.java b/rocketmq-tools/src/main/java/com/alibaba/rocketmq/tools/command/broker/BrokerStatsSubCommand.java new file mode 100644 index 00000000..979ad8a2 --- /dev/null +++ b/rocketmq-tools/src/main/java/com/alibaba/rocketmq/tools/command/broker/BrokerStatsSubCommand.java @@ -0,0 +1,91 @@ +/** + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.rocketmq.tools.command.broker; + +import java.util.Iterator; +import java.util.Map.Entry; +import java.util.TreeMap; + +import org.apache.commons.cli.CommandLine; +import org.apache.commons.cli.Option; +import org.apache.commons.cli.Options; + +import com.alibaba.rocketmq.common.protocol.body.KVTable; +import com.alibaba.rocketmq.tools.admin.DefaultMQAdminExt; +import com.alibaba.rocketmq.tools.command.SubCommand; + + +/** + * 获取Broker运行时统计信息 + * + * @author shijia.wxr + * @since 2013-8-14 + */ +public class BrokerStatsSubCommand implements SubCommand { + + @Override + public String commandName() { + return "brokerStats"; + } + + + @Override + public String commandDesc() { + return "Fetch broker runtime stats data"; + } + + + @Override + public Options buildCommandlineOptions(Options options) { + Option opt = new Option("b", "brokerAddr", true, "Broker address"); + opt.setRequired(true); + options.addOption(opt); + + return options; + } + + + @Override + public void execute(CommandLine commandLine, Options options) { + DefaultMQAdminExt defaultMQAdminExt = new DefaultMQAdminExt(); + + defaultMQAdminExt.setInstanceName(Long.toString(System.currentTimeMillis())); + + try { + defaultMQAdminExt.start(); + + String brokerAddr = commandLine.getOptionValue('b').trim(); + + KVTable kvTable = defaultMQAdminExt.fetchBrokerRuntimeStats(brokerAddr); + + // 为了排序 + TreeMap tmp = new TreeMap(); + tmp.putAll(kvTable.getTable()); + + Iterator> it = tmp.entrySet().iterator(); + while (it.hasNext()) { + Entry next = it.next(); + System.out.printf("%-32s: %s\n", next.getKey(), next.getValue()); + } + } + catch (Exception e) { + e.printStackTrace(); + } + finally { + defaultMQAdminExt.shutdown(); + } + } +} diff --git a/rocketmq-tools/src/main/java/com/alibaba/rocketmq/tools/command/broker/UpdateBrokerConfigSubCommand.java b/rocketmq-tools/src/main/java/com/alibaba/rocketmq/tools/command/broker/UpdateBrokerConfigSubCommand.java new file mode 100644 index 00000000..be34f9ab --- /dev/null +++ b/rocketmq-tools/src/main/java/com/alibaba/rocketmq/tools/command/broker/UpdateBrokerConfigSubCommand.java @@ -0,0 +1,118 @@ +/** + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.rocketmq.tools.command.broker; + +import java.util.Properties; +import java.util.Set; + +import org.apache.commons.cli.CommandLine; +import org.apache.commons.cli.Option; +import org.apache.commons.cli.Options; + +import com.alibaba.rocketmq.common.MixAll; +import com.alibaba.rocketmq.tools.admin.DefaultMQAdminExt; +import com.alibaba.rocketmq.tools.command.CommandUtil; +import com.alibaba.rocketmq.tools.command.SubCommand; + + +/** + * 更新Broker配置文件 + * + * @author shijia.wxr + * @since 2013-10-20 + */ +public class UpdateBrokerConfigSubCommand implements SubCommand { + + @Override + public String commandName() { + return "updateBrokerConfig"; + } + + + @Override + public String commandDesc() { + return "Update broker's config"; + } + + + @Override + public Options buildCommandlineOptions(Options options) { + Option opt = new Option("b", "brokerAddr", true, "update which broker"); + opt.setRequired(false); + options.addOption(opt); + + opt = new Option("c", "clusterName", true, "update which cluster"); + opt.setRequired(false); + options.addOption(opt); + + opt = new Option("k", "key", true, "config key"); + opt.setRequired(true); + options.addOption(opt); + + opt = new Option("v", "value", true, "config value"); + opt.setRequired(true); + options.addOption(opt); + + return options; + } + + + @Override + public void execute(CommandLine commandLine, Options options) { + DefaultMQAdminExt defaultMQAdminExt = new DefaultMQAdminExt(); + + defaultMQAdminExt.setInstanceName(Long.toString(System.currentTimeMillis())); + + try { + String key = commandLine.getOptionValue('k').trim(); + String value = commandLine.getOptionValue('v').trim(); + Properties properties = new Properties(); + properties.put(key, value); + + if (commandLine.hasOption('b')) { + String brokerAddr = commandLine.getOptionValue('b').trim(); + + defaultMQAdminExt.start(); + + defaultMQAdminExt.updateBrokerConfig(brokerAddr, properties); + System.out.printf("update broker config success, %s\n", brokerAddr); + return; + + } + else if (commandLine.hasOption('c')) { + String clusterName = commandLine.getOptionValue('c').trim(); + + defaultMQAdminExt.start(); + + Set masterSet = + CommandUtil.fetchMasterAddrByClusterName(defaultMQAdminExt, clusterName); + for (String brokerAddr : masterSet) { + defaultMQAdminExt.updateBrokerConfig(brokerAddr, properties); + System.out.printf("update broker config success, %s\n", brokerAddr); + } + return; + } + + MixAll.printCommandLineHelp("mqadmin " + this.commandName(), options); + } + catch (Exception e) { + e.printStackTrace(); + } + finally { + defaultMQAdminExt.shutdown(); + } + } +} diff --git a/rocketmq-tools/src/main/java/com/alibaba/rocketmq/tools/command/cluster/ClusterListSubCommand.java b/rocketmq-tools/src/main/java/com/alibaba/rocketmq/tools/command/cluster/ClusterListSubCommand.java new file mode 100644 index 00000000..5c99641a --- /dev/null +++ b/rocketmq-tools/src/main/java/com/alibaba/rocketmq/tools/command/cluster/ClusterListSubCommand.java @@ -0,0 +1,255 @@ +/** + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.rocketmq.tools.command.cluster; + +import java.util.Iterator; +import java.util.Map; +import java.util.Set; +import java.util.TreeSet; + +import org.apache.commons.cli.CommandLine; +import org.apache.commons.cli.Option; +import org.apache.commons.cli.Options; + +import com.alibaba.rocketmq.client.exception.MQBrokerException; +import com.alibaba.rocketmq.common.protocol.body.ClusterInfo; +import com.alibaba.rocketmq.common.protocol.body.KVTable; +import com.alibaba.rocketmq.common.protocol.route.BrokerData; +import com.alibaba.rocketmq.remoting.exception.RemotingConnectException; +import com.alibaba.rocketmq.remoting.exception.RemotingSendRequestException; +import com.alibaba.rocketmq.remoting.exception.RemotingTimeoutException; +import com.alibaba.rocketmq.tools.admin.DefaultMQAdminExt; +import com.alibaba.rocketmq.tools.command.SubCommand; + + +/** + * 查看集群信息 + * + * @author shijia.wxr + * @since 2013-7-25 + */ +public class ClusterListSubCommand implements SubCommand { + + @Override + public String commandName() { + return "clusterList"; + } + + + @Override + public String commandDesc() { + return "List all of clusters"; + } + + + @Override + public Options buildCommandlineOptions(Options options) { + Option opt = new Option("m", "moreStats", false, "Print more stats"); + opt.setRequired(false); + options.addOption(opt); + + return options; + } + + + private void printClusterBaseInfo(final DefaultMQAdminExt defaultMQAdminExt) + throws RemotingConnectException, RemotingTimeoutException, RemotingSendRequestException, + InterruptedException, MQBrokerException { + + ClusterInfo clusterInfoSerializeWrapper = defaultMQAdminExt.examineBrokerClusterInfo(); + + System.out.printf("%-16s %-32s %-4s %-22s %-22s %11s %11s\n",// + "#Cluster Name",// + "#Broker Name",// + "#BID",// + "#Addr",// + "#Version",// + "#InTPS",// + "#OutTPS"// + ); + + Iterator>> itCluster = + clusterInfoSerializeWrapper.getClusterAddrTable().entrySet().iterator(); + while (itCluster.hasNext()) { + Map.Entry> next = itCluster.next(); + String clusterName = next.getKey(); + TreeSet brokerNameSet = new TreeSet(); + brokerNameSet.addAll(next.getValue()); + + for (String brokerName : brokerNameSet) { + BrokerData brokerData = clusterInfoSerializeWrapper.getBrokerAddrTable().get(brokerName); + if (brokerData != null) { + + Iterator> itAddr = + brokerData.getBrokerAddrs().entrySet().iterator(); + while (itAddr.hasNext()) { + Map.Entry next1 = itAddr.next(); + double in = 0; + double out = 0; + String version = ""; + + try { + KVTable kvTable = defaultMQAdminExt.fetchBrokerRuntimeStats(next1.getValue()); + String putTps = kvTable.getTable().get("putTps"); + String getTransferedTps = kvTable.getTable().get("getTransferedTps"); + version = kvTable.getTable().get("brokerVersionDesc"); + { + String[] tpss = putTps.split(" "); + if (tpss != null && tpss.length > 0) { + in = Double.parseDouble(tpss[0]); + } + } + + { + String[] tpss = getTransferedTps.split(" "); + if (tpss != null && tpss.length > 0) { + out = Double.parseDouble(tpss[0]); + } + } + } + catch (Exception e) { + } + + System.out.printf("%-16s %-32s %-4s %-22s %-22s %11.2f %11.2f\n",// + clusterName,// + brokerName,// + next1.getKey().longValue(),// + next1.getValue(),// + version,// + in,// + out// + ); + } + } + } + + if (itCluster.hasNext()) { + System.out.println(""); + } + } + } + + + private void printClusterMoreStats(final DefaultMQAdminExt defaultMQAdminExt) + throws RemotingConnectException, RemotingTimeoutException, RemotingSendRequestException, + InterruptedException, MQBrokerException { + + ClusterInfo clusterInfoSerializeWrapper = defaultMQAdminExt.examineBrokerClusterInfo(); + + System.out.printf("%-16s %-32s %14s %14s %14s %14s\n",// + "#Cluster Name",// + "#Broker Name",// + "#InTotalYest",// + "#OutTotalYest",// + "#InTotalToday",// + "#OutTotalToday"// + ); + + Iterator>> itCluster = + clusterInfoSerializeWrapper.getClusterAddrTable().entrySet().iterator(); + while (itCluster.hasNext()) { + Map.Entry> next = itCluster.next(); + String clusterName = next.getKey(); + TreeSet brokerNameSet = new TreeSet(); + brokerNameSet.addAll(next.getValue()); + + for (String brokerName : brokerNameSet) { + BrokerData brokerData = clusterInfoSerializeWrapper.getBrokerAddrTable().get(brokerName); + if (brokerData != null) { + + Iterator> itAddr = + brokerData.getBrokerAddrs().entrySet().iterator(); + while (itAddr.hasNext()) { + Map.Entry next1 = itAddr.next(); + long InTotalYest = 0; + long OutTotalYest = 0; + long InTotalToday = 0; + long OutTotalToday = 0; + + try { + KVTable kvTable = defaultMQAdminExt.fetchBrokerRuntimeStats(next1.getValue()); + String msgPutTotalYesterdayMorning = + kvTable.getTable().get("msgPutTotalYesterdayMorning"); + String msgPutTotalTodayMorning = + kvTable.getTable().get("msgPutTotalTodayMorning"); + String msgPutTotalTodayNow = kvTable.getTable().get("msgPutTotalTodayNow"); + String msgGetTotalYesterdayMorning = + kvTable.getTable().get("msgGetTotalYesterdayMorning"); + String msgGetTotalTodayMorning = + kvTable.getTable().get("msgGetTotalTodayMorning"); + String msgGetTotalTodayNow = kvTable.getTable().get("msgGetTotalTodayNow"); + + InTotalYest = + Long.parseLong(msgPutTotalTodayMorning) + - Long.parseLong(msgPutTotalYesterdayMorning); + OutTotalYest = + Long.parseLong(msgGetTotalTodayMorning) + - Long.parseLong(msgGetTotalYesterdayMorning); + + InTotalToday = + Long.parseLong(msgPutTotalTodayNow) + - Long.parseLong(msgPutTotalTodayMorning); + OutTotalToday = + Long.parseLong(msgGetTotalTodayNow) + - Long.parseLong(msgGetTotalTodayMorning); + + } + catch (Exception e) { + } + + System.out.printf("%-16s %-32s %14d %14d %14d %14d\n",// + clusterName,// + brokerName,// + InTotalYest,// + OutTotalYest,// + InTotalToday,// + OutTotalToday// + ); + } + } + } + + if (itCluster.hasNext()) { + System.out.println(""); + } + } + } + + + @Override + public void execute(final CommandLine commandLine, final Options options) { + DefaultMQAdminExt defaultMQAdminExt = new DefaultMQAdminExt(); + + defaultMQAdminExt.setInstanceName(Long.toString(System.currentTimeMillis())); + + try { + defaultMQAdminExt.start(); + + if (commandLine.hasOption('m')) { + this.printClusterMoreStats(defaultMQAdminExt); + } + else { + this.printClusterBaseInfo(defaultMQAdminExt); + } + } + catch (Exception e) { + e.printStackTrace(); + } + finally { + defaultMQAdminExt.shutdown(); + } + } +} diff --git a/rocketmq-tools/src/main/java/com/alibaba/rocketmq/tools/command/connection/ConsumerConnectionSubCommand.java b/rocketmq-tools/src/main/java/com/alibaba/rocketmq/tools/command/connection/ConsumerConnectionSubCommand.java new file mode 100644 index 00000000..2247570b --- /dev/null +++ b/rocketmq-tools/src/main/java/com/alibaba/rocketmq/tools/command/connection/ConsumerConnectionSubCommand.java @@ -0,0 +1,115 @@ +/** + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.rocketmq.tools.command.connection; + +import java.util.Iterator; +import java.util.Map.Entry; + +import org.apache.commons.cli.CommandLine; +import org.apache.commons.cli.Option; +import org.apache.commons.cli.Options; + +import com.alibaba.rocketmq.common.MQVersion; +import com.alibaba.rocketmq.common.protocol.body.Connection; +import com.alibaba.rocketmq.common.protocol.body.ConsumerConnection; +import com.alibaba.rocketmq.common.protocol.heartbeat.SubscriptionData; +import com.alibaba.rocketmq.tools.admin.DefaultMQAdminExt; +import com.alibaba.rocketmq.tools.command.SubCommand; + + +/** + * 查询Consumer的网络连接,以及客户端版本号,订阅关系等 + * + * @author shijia.wxr + * @since 2013-10-13 + */ +public class ConsumerConnectionSubCommand implements SubCommand { + + @Override + public String commandName() { + return "consumerConnection"; + } + + + @Override + public String commandDesc() { + return "Query consumer's socket connection, client version and subscription"; + } + + + @Override + public Options buildCommandlineOptions(Options options) { + Option opt = new Option("g", "consumerGroup", true, "consumer group name"); + opt.setRequired(true); + options.addOption(opt); + + return options; + } + + + @Override + public void execute(CommandLine commandLine, Options options) { + DefaultMQAdminExt defaultMQAdminExt = new DefaultMQAdminExt(); + + defaultMQAdminExt.setInstanceName(Long.toString(System.currentTimeMillis())); + + try { + defaultMQAdminExt.start(); + + String group = commandLine.getOptionValue('g').trim(); + + ConsumerConnection cc = defaultMQAdminExt.examineConsumerConnectionInfo(group); + + // 打印连接 + int i = 1; + for (Connection conn : cc.getConnectionSet()) { + System.out.printf("%03d %-32s %-22s %-8s %s\n",// + i++,// + conn.getClientId(),// + conn.getClientAddr(),// + conn.getLanguage(),// + MQVersion.getVersionDesc(conn.getVersion())// + ); + } + + // 打印订阅关系 + System.out.println("\nBelow is subscription:"); + Iterator> it = cc.getSubscriptionTable().entrySet().iterator(); + i = 1; + while (it.hasNext()) { + Entry entry = it.next(); + SubscriptionData sd = entry.getValue(); + System.out.printf("%03d Topic: %-40s SubExpression: %s\n",// + i++,// + sd.getTopic(),// + sd.getSubString()// + ); + } + + // 打印其他订阅参数 + System.out.println(""); + System.out.printf("ConsumeType: %s\n", cc.getConsumeType()); + System.out.printf("MessageModel: %s\n", cc.getMessageModel()); + System.out.printf("ConsumeFromWhere: %s\n", cc.getConsumeFromWhere()); + } + catch (Exception e) { + e.printStackTrace(); + } + finally { + defaultMQAdminExt.shutdown(); + } + } +} diff --git a/rocketmq-tools/src/main/java/com/alibaba/rocketmq/tools/command/connection/ProducerConnectionSubCommand.java b/rocketmq-tools/src/main/java/com/alibaba/rocketmq/tools/command/connection/ProducerConnectionSubCommand.java new file mode 100644 index 00000000..f426d19d --- /dev/null +++ b/rocketmq-tools/src/main/java/com/alibaba/rocketmq/tools/command/connection/ProducerConnectionSubCommand.java @@ -0,0 +1,96 @@ +/** + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.rocketmq.tools.command.connection; + +import org.apache.commons.cli.CommandLine; +import org.apache.commons.cli.Option; +import org.apache.commons.cli.Options; + +import com.alibaba.rocketmq.common.MQVersion; +import com.alibaba.rocketmq.common.protocol.body.Connection; +import com.alibaba.rocketmq.common.protocol.body.ProducerConnection; +import com.alibaba.rocketmq.tools.admin.DefaultMQAdminExt; +import com.alibaba.rocketmq.tools.command.SubCommand; + + +/** + * 查询Producer的网络连接 + * + * @author shijia.wxr + * @since 2013-10-13 + */ +public class ProducerConnectionSubCommand implements SubCommand { + + @Override + public String commandName() { + return "producerConnection"; + } + + + @Override + public String commandDesc() { + return "Query producer's socket connection and client version"; + } + + + @Override + public Options buildCommandlineOptions(Options options) { + Option opt = new Option("g", "producerGroup", true, "producer group name"); + opt.setRequired(true); + options.addOption(opt); + + // topic必须设置 + opt = new Option("t", "topic", true, "topic name"); + opt.setRequired(true); + options.addOption(opt); + + return options; + } + + + @Override + public void execute(CommandLine commandLine, Options options) { + DefaultMQAdminExt defaultMQAdminExt = new DefaultMQAdminExt(); + + defaultMQAdminExt.setInstanceName(Long.toString(System.currentTimeMillis())); + + try { + defaultMQAdminExt.start(); + + String group = commandLine.getOptionValue('g').trim(); + String topic = commandLine.getOptionValue('t').trim(); + + ProducerConnection pc = defaultMQAdminExt.examineProducerConnectionInfo(group, topic); + + int i = 1; + for (Connection conn : pc.getConnectionSet()) { + System.out.printf("%04d %-32s %-22s %-8s %s\n",// + i++,// + conn.getClientId(),// + conn.getClientAddr(),// + conn.getLanguage(),// + MQVersion.getVersionDesc(conn.getVersion())// + ); + } + } + catch (Exception e) { + e.printStackTrace(); + } + finally { + defaultMQAdminExt.shutdown(); + } + } +} diff --git a/rocketmq-tools/src/main/java/com/alibaba/rocketmq/tools/command/consumer/ConsumerProgressSubCommand.java b/rocketmq-tools/src/main/java/com/alibaba/rocketmq/tools/command/consumer/ConsumerProgressSubCommand.java new file mode 100644 index 00000000..747e2583 --- /dev/null +++ b/rocketmq-tools/src/main/java/com/alibaba/rocketmq/tools/command/consumer/ConsumerProgressSubCommand.java @@ -0,0 +1,320 @@ +/** + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.rocketmq.tools.command.consumer; + +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; + +import org.apache.commons.cli.CommandLine; +import org.apache.commons.cli.Option; +import org.apache.commons.cli.Options; +import org.slf4j.Logger; + +import com.alibaba.rocketmq.client.log.ClientLogger; +import com.alibaba.rocketmq.common.MQVersion; +import com.alibaba.rocketmq.common.MixAll; +import com.alibaba.rocketmq.common.UtilAll; +import com.alibaba.rocketmq.common.admin.ConsumeStats; +import com.alibaba.rocketmq.common.admin.OffsetWrapper; +import com.alibaba.rocketmq.common.message.MessageQueue; +import com.alibaba.rocketmq.common.protocol.body.ConsumerConnection; +import com.alibaba.rocketmq.common.protocol.body.TopicList; +import com.alibaba.rocketmq.common.protocol.heartbeat.ConsumeType; +import com.alibaba.rocketmq.common.protocol.heartbeat.MessageModel; +import com.alibaba.rocketmq.tools.admin.DefaultMQAdminExt; +import com.alibaba.rocketmq.tools.command.SubCommand; + + +/** + * 查看订阅组消费状态,消费进度 + * + * @author shijia.wxr + * @since 2013-8-11 + */ +public class ConsumerProgressSubCommand implements SubCommand { + private final Logger log = ClientLogger.getLog(); + + + @Override + public String commandName() { + return "consumerProgress"; + } + + + @Override + public String commandDesc() { + return "Query consumers's progress, speed"; + } + + + @Override + public Options buildCommandlineOptions(Options options) { + Option opt = new Option("g", "groupName", true, "consumer group name"); + opt.setRequired(false); + options.addOption(opt); + + return options; + } + + + @Override + public void execute(CommandLine commandLine, Options options) { + DefaultMQAdminExt defaultMQAdminExt = new DefaultMQAdminExt(); + + defaultMQAdminExt.setInstanceName(Long.toString(System.currentTimeMillis())); + + try { + defaultMQAdminExt.start(); + + // 查询特定consumer + if (commandLine.hasOption('g')) { + String consumerGroup = commandLine.getOptionValue('g').trim(); + ConsumeStats consumeStats = defaultMQAdminExt.examineConsumeStats(consumerGroup); + + List mqList = new LinkedList(); + mqList.addAll(consumeStats.getOffsetTable().keySet()); + Collections.sort(mqList); + + System.out.printf("%-32s %-32s %-4s %-20s %-20s %s\n",// + "#Topic",// + "#Broker Name",// + "#QID",// + "#Broker Offset",// + "#Consumer Offset",// + "#Diff" // + ); + + long diffTotal = 0L; + + for (MessageQueue mq : mqList) { + OffsetWrapper offsetWrapper = consumeStats.getOffsetTable().get(mq); + + long diff = offsetWrapper.getBrokerOffset() - offsetWrapper.getConsumerOffset(); + diffTotal += diff; + + System.out.printf("%-32s %-32s %-4d %-20d %-20d %d\n",// + UtilAll.frontStringAtLeast(mq.getTopic(), 32),// + UtilAll.frontStringAtLeast(mq.getBrokerName(), 32),// + mq.getQueueId(),// + offsetWrapper.getBrokerOffset(),// + offsetWrapper.getConsumerOffset(),// + diff // + ); + } + + System.out.println(""); + System.out.printf("Consume TPS: %d\n", consumeStats.getConsumeTps()); + System.out.printf("Diff Total: %d\n", diffTotal); + } + // 查询全部 + else { + System.out.printf("%-32s %-6s %-24s %-5s %-14s %-7s %s\n",// + "#Group",// + "#Count",// + "#Version",// + "#Type",// + "#Model",// + "#TPS",// + "#Diff Total"// + ); + + List groupConsumeInfoList = new LinkedList(); + + TopicList topicList = defaultMQAdminExt.fetchAllTopicList(); + for (String topic : topicList.getTopicList()) { + if (topic.startsWith(MixAll.RETRY_GROUP_TOPIC_PREFIX)) { + String consumerGroup = topic.substring(MixAll.RETRY_GROUP_TOPIC_PREFIX.length()); + + try { + ConsumeStats consumeStats = null; + try { + consumeStats = defaultMQAdminExt.examineConsumeStats(consumerGroup); + } + catch (Exception e) { + log.warn("examineConsumeStats exception, " + consumerGroup, e); + } + + ConsumerConnection cc = null; + try { + cc = defaultMQAdminExt.examineConsumerConnectionInfo(consumerGroup); + } + catch (Exception e) { + log.warn("examineConsumerConnectionInfo exception, " + consumerGroup, e); + } + + GroupConsumeInfo groupConsumeInfo = new GroupConsumeInfo(); + groupConsumeInfo.setGroup(consumerGroup); + + if (consumeStats != null) { + groupConsumeInfo.setConsumeTps((int) consumeStats.getConsumeTps()); + groupConsumeInfo.setDiffTotal(consumeStats.computeTotalDiff()); + } + + if (cc != null) { + groupConsumeInfo.setCount(cc.getConnectionSet().size()); + groupConsumeInfo.setMessageModel(cc.getMessageModel()); + groupConsumeInfo.setConsumeType(cc.getConsumeType()); + groupConsumeInfo.setVersion(cc.computeMinVersion()); + } + + groupConsumeInfoList.add(groupConsumeInfo); + } + catch (Exception e) { + log.warn("examineConsumeStats or examineConsumerConnectionInfo exception, " + + consumerGroup, e); + } + } + } + + Collections.sort(groupConsumeInfoList); + + for (GroupConsumeInfo info : groupConsumeInfoList) { + System.out.printf("%-32s %-6d %-24s %-5s %-14s %-7d %d\n",// + UtilAll.frontStringAtLeast(info.getGroup(), 32),// + info.getCount(),// + info.versionDesc(),// + info.consumeTypeDesc(),// + info.messageModelDesc(),// + info.getConsumeTps(),// + info.getDiffTotal()// + ); + } + } + } + catch (Exception e) { + e.printStackTrace(); + } + finally { + defaultMQAdminExt.shutdown(); + } + } +} + + +class GroupConsumeInfo implements Comparable { + private String group; + private int version; + private int count; + private ConsumeType consumeType; + private MessageModel messageModel; + private int consumeTps; + private long diffTotal; + + + public String getGroup() { + return group; + } + + + public String consumeTypeDesc() { + if (this.count != 0) { + return this.getConsumeType() == ConsumeType.CONSUME_ACTIVELY ? "PULL" : "PUSH"; + } + return ""; + } + + + public String messageModelDesc() { + if (this.count != 0 && this.getConsumeType() == ConsumeType.CONSUME_PASSIVELY) { + return this.getMessageModel().toString(); + } + return ""; + } + + + public String versionDesc() { + if (this.count != 0) { + return MQVersion.getVersionDesc(this.version); + } + return ""; + } + + + public void setGroup(String group) { + this.group = group; + } + + + public int getCount() { + return count; + } + + + public void setCount(int count) { + this.count = count; + } + + + public ConsumeType getConsumeType() { + return consumeType; + } + + + public void setConsumeType(ConsumeType consumeType) { + this.consumeType = consumeType; + } + + + public MessageModel getMessageModel() { + return messageModel; + } + + + public void setMessageModel(MessageModel messageModel) { + this.messageModel = messageModel; + } + + + public long getDiffTotal() { + return diffTotal; + } + + + public void setDiffTotal(long diffTotal) { + this.diffTotal = diffTotal; + } + + + @Override + public int compareTo(GroupConsumeInfo o) { + if (this.count != o.count) { + return o.count - this.count; + } + + return (int) (o.diffTotal - diffTotal); + } + + + public int getConsumeTps() { + return consumeTps; + } + + + public void setConsumeTps(int consumeTps) { + this.consumeTps = consumeTps; + } + + + public int getVersion() { + return version; + } + + + public void setVersion(int version) { + this.version = version; + } +} diff --git a/rocketmq-tools/src/main/java/com/alibaba/rocketmq/tools/command/consumer/DeleteSubscriptionGroupCommand.java b/rocketmq-tools/src/main/java/com/alibaba/rocketmq/tools/command/consumer/DeleteSubscriptionGroupCommand.java new file mode 100644 index 00000000..0de12281 --- /dev/null +++ b/rocketmq-tools/src/main/java/com/alibaba/rocketmq/tools/command/consumer/DeleteSubscriptionGroupCommand.java @@ -0,0 +1,109 @@ +/** + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.rocketmq.tools.command.consumer; + +import java.util.Set; + +import org.apache.commons.cli.CommandLine; +import org.apache.commons.cli.Option; +import org.apache.commons.cli.Options; + +import com.alibaba.rocketmq.common.MixAll; +import com.alibaba.rocketmq.tools.admin.DefaultMQAdminExt; +import com.alibaba.rocketmq.tools.command.CommandUtil; +import com.alibaba.rocketmq.tools.command.SubCommand; + + +/** + * 删除订阅组配置命令 + * + * @author manhong.yqd + * @since 2013-8-22 + */ +public class DeleteSubscriptionGroupCommand implements SubCommand { + @Override + public String commandName() { + return "deleteSubGroup"; + } + + + @Override + public String commandDesc() { + return "delete subscription group from broker."; + } + + + @Override + public Options buildCommandlineOptions(Options options) { + Option opt = new Option("b", "brokerAddr", true, "delete subscription group from which broker"); + opt.setRequired(false); + options.addOption(opt); + + opt = new Option("c", "clusterName", true, "delete subscription group from which cluster"); + opt.setRequired(false); + options.addOption(opt); + + opt = new Option("g", "groupName", true, "subscription group name"); + opt.setRequired(true); + options.addOption(opt); + + return options; + } + + + @Override + public void execute(CommandLine commandLine, Options options) { + DefaultMQAdminExt adminExt = new DefaultMQAdminExt(); + adminExt.setInstanceName(Long.toString(System.currentTimeMillis())); + try { + // groupName + String groupName = commandLine.getOptionValue('g').trim(); + + if (commandLine.hasOption('b')) { + String addr = commandLine.getOptionValue('b').trim(); + adminExt.start(); + + adminExt.deleteSubscriptionGroup(addr, groupName); + System.out.printf("delete subscription group [%s] from broker [%s] success.\n", groupName, + addr); + + return; + } + else if (commandLine.hasOption('c')) { + String clusterName = commandLine.getOptionValue('c').trim(); + adminExt.start(); + + Set masterSet = CommandUtil.fetchMasterAddrByClusterName(adminExt, clusterName); + for (String master : masterSet) { + adminExt.deleteSubscriptionGroup(master, groupName); + System.out.printf( + "delete subscription group [%s] from broker [%s] in cluster [%s] success.\n", + groupName, master, clusterName); + } + + return; + } + + MixAll.printCommandLineHelp("mqadmin " + this.commandName(), options); + } + catch (Exception e) { + e.printStackTrace(); + } + finally { + adminExt.shutdown(); + } + } +} diff --git a/rocketmq-tools/src/main/java/com/alibaba/rocketmq/tools/command/consumer/UpdateSubGroupSubCommand.java b/rocketmq-tools/src/main/java/com/alibaba/rocketmq/tools/command/consumer/UpdateSubGroupSubCommand.java new file mode 100644 index 00000000..120a18ab --- /dev/null +++ b/rocketmq-tools/src/main/java/com/alibaba/rocketmq/tools/command/consumer/UpdateSubGroupSubCommand.java @@ -0,0 +1,187 @@ +/** + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.rocketmq.tools.command.consumer; + +import java.util.Set; + +import org.apache.commons.cli.CommandLine; +import org.apache.commons.cli.Option; +import org.apache.commons.cli.Options; + +import com.alibaba.rocketmq.common.MixAll; +import com.alibaba.rocketmq.common.subscription.SubscriptionGroupConfig; +import com.alibaba.rocketmq.tools.admin.DefaultMQAdminExt; +import com.alibaba.rocketmq.tools.command.CommandUtil; +import com.alibaba.rocketmq.tools.command.SubCommand; + + +/** + * 修改、创建订阅组配置命令 + * + * @author shijia.wxr + * @since 2013-7-21 + */ +public class UpdateSubGroupSubCommand implements SubCommand { + + @Override + public String commandName() { + return "updateSubGroup"; + } + + + @Override + public String commandDesc() { + return "Update or create subscription group"; + } + + + @Override + public Options buildCommandlineOptions(Options options) { + Option opt = new Option("b", "brokerAddr", true, "create subscription group to which broker"); + opt.setRequired(false); + options.addOption(opt); + + opt = new Option("c", "clusterName", true, "create subscription group to which cluster"); + opt.setRequired(false); + options.addOption(opt); + + opt = new Option("g", "groupName", true, "consumer group name"); + opt.setRequired(true); + options.addOption(opt); + + opt = new Option("s", "consumeEnable", true, "consume enable"); + opt.setRequired(false); + options.addOption(opt); + + opt = new Option("m", "consumeFromMinEnable", true, "from min offset"); + opt.setRequired(false); + options.addOption(opt); + + opt = new Option("d", "consumeBroadcastEnable", true, "broadcast"); + opt.setRequired(false); + options.addOption(opt); + + opt = new Option("q", "retryQueueNums", true, "retry queue nums"); + opt.setRequired(false); + options.addOption(opt); + + opt = new Option("r", "retryMaxTimes", true, "retry max times"); + opt.setRequired(false); + options.addOption(opt); + + opt = new Option("i", "brokerId", true, "consumer from which broker id"); + opt.setRequired(false); + options.addOption(opt); + + opt = new Option("w", "whichBrokerWhenConsumeSlowly", true, "which broker id when consume slowly"); + opt.setRequired(false); + options.addOption(opt); + + return options; + } + + + @Override + public void execute(final CommandLine commandLine, final Options options) { + DefaultMQAdminExt defaultMQAdminExt = new DefaultMQAdminExt(); + + defaultMQAdminExt.setInstanceName(Long.toString(System.currentTimeMillis())); + + try { + SubscriptionGroupConfig subscriptionGroupConfig = new SubscriptionGroupConfig(); + subscriptionGroupConfig.setConsumeBroadcastEnable(false); + subscriptionGroupConfig.setConsumeFromMinEnable(false); + + // groupName + subscriptionGroupConfig.setGroupName(commandLine.getOptionValue('g').trim()); + + // consumeEnable + if (commandLine.hasOption('s')) { + subscriptionGroupConfig.setConsumeEnable(Boolean.parseBoolean(commandLine.getOptionValue('s') + .trim())); + } + + // consumeFromMinEnable + if (commandLine.hasOption('m')) { + subscriptionGroupConfig.setConsumeFromMinEnable(Boolean.parseBoolean(commandLine + .getOptionValue('m').trim())); + } + + // consumeBroadcastEnable + if (commandLine.hasOption('d')) { + subscriptionGroupConfig.setConsumeBroadcastEnable(Boolean.parseBoolean(commandLine + .getOptionValue('d').trim())); + } + + // retryQueueNums + if (commandLine.hasOption('q')) { + subscriptionGroupConfig.setRetryQueueNums(Integer.parseInt(commandLine.getOptionValue('q') + .trim())); + } + + // retryMaxTimes + if (commandLine.hasOption('r')) { + subscriptionGroupConfig.setRetryMaxTimes(Integer.parseInt(commandLine.getOptionValue('r') + .trim())); + } + + // brokerId + if (commandLine.hasOption('i')) { + subscriptionGroupConfig.setBrokerId(Long.parseLong(commandLine.getOptionValue('i').trim())); + } + + // whichBrokerWhenConsumeSlowly + if (commandLine.hasOption('w')) { + subscriptionGroupConfig.setWhichBrokerWhenConsumeSlowly(Long.parseLong(commandLine + .getOptionValue('w').trim())); + } + + if (commandLine.hasOption('b')) { + String addr = commandLine.getOptionValue('b').trim(); + + defaultMQAdminExt.start(); + + defaultMQAdminExt.createAndUpdateSubscriptionGroupConfig(addr, subscriptionGroupConfig); + System.out.printf("create subscription group to %s success.\n", addr); + System.out.println(subscriptionGroupConfig); + return; + + } + else if (commandLine.hasOption('c')) { + String clusterName = commandLine.getOptionValue('c').trim(); + + defaultMQAdminExt.start(); + + Set masterSet = + CommandUtil.fetchMasterAddrByClusterName(defaultMQAdminExt, clusterName); + for (String addr : masterSet) { + defaultMQAdminExt.createAndUpdateSubscriptionGroupConfig(addr, subscriptionGroupConfig); + System.out.printf("create subscription group to %s success.\n", addr); + } + System.out.println(subscriptionGroupConfig); + return; + } + + MixAll.printCommandLineHelp("mqadmin " + this.commandName(), options); + } + catch (Exception e) { + e.printStackTrace(); + } + finally { + defaultMQAdminExt.shutdown(); + } + } +} diff --git a/rocketmq-tools/src/main/java/com/alibaba/rocketmq/tools/command/message/QueryMsgByIdSubCommand.java b/rocketmq-tools/src/main/java/com/alibaba/rocketmq/tools/command/message/QueryMsgByIdSubCommand.java new file mode 100644 index 00000000..7059f23b --- /dev/null +++ b/rocketmq-tools/src/main/java/com/alibaba/rocketmq/tools/command/message/QueryMsgByIdSubCommand.java @@ -0,0 +1,180 @@ +/** + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.rocketmq.tools.command.message; + +import java.io.DataOutputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; + +import org.apache.commons.cli.CommandLine; +import org.apache.commons.cli.Option; +import org.apache.commons.cli.Options; + +import com.alibaba.rocketmq.client.exception.MQBrokerException; +import com.alibaba.rocketmq.client.exception.MQClientException; +import com.alibaba.rocketmq.common.UtilAll; +import com.alibaba.rocketmq.common.message.MessageExt; +import com.alibaba.rocketmq.remoting.common.RemotingHelper; +import com.alibaba.rocketmq.remoting.exception.RemotingException; +import com.alibaba.rocketmq.tools.admin.DefaultMQAdminExt; +import com.alibaba.rocketmq.tools.command.SubCommand; + + +/** + * 根据消息Id查询消息 + * + * @author shijia.wxr + * @since 2013-8-12 + */ +public class QueryMsgByIdSubCommand implements SubCommand { + + @Override + public String commandName() { + return "queryMsgById"; + } + + + @Override + public String commandDesc() { + return "Query Message by Id"; + } + + + @Override + public Options buildCommandlineOptions(Options options) { + Option opt = new Option("i", "msgId", true, "Message Id"); + opt.setRequired(true); + options.addOption(opt); + + return options; + } + + + public static void queryById(final DefaultMQAdminExt admin, final String msgId) throws MQClientException, + RemotingException, MQBrokerException, InterruptedException, IOException { + admin.start(); + MessageExt msg = admin.viewMessage(msgId); + + // 存储消息 body 到指定路径 + String bodyTmpFilePath = createBodyFile(msg); + + System.out.printf("%-20s %s\n",// + "Topic:",// + msg.getTopic()// + ); + + System.out.printf("%-20s %s\n",// + "Tags:",// + "[" + msg.getTags() + "]"// + ); + + System.out.printf("%-20s %s\n",// + "Keys:",// + "[" + msg.getKeys() + "]"// + ); + + System.out.printf("%-20s %d\n",// + "Queue ID:",// + msg.getQueueId()// + ); + + System.out.printf("%-20s %d\n",// + "Queue Offset:",// + msg.getQueueOffset()// + ); + + System.out.printf("%-20s %d\n",// + "CommitLog Offset:",// + msg.getCommitLogOffset()// + ); + + System.out.printf("%-20s %s\n",// + "Born Timestamp:",// + UtilAll.timeMillisToHumanString2(msg.getBornTimestamp())// + ); + + System.out.printf("%-20s %s\n",// + "Store Timestamp:",// + UtilAll.timeMillisToHumanString2(msg.getStoreTimestamp())// + ); + + System.out.printf("%-20s %s\n",// + "Born Host:",// + RemotingHelper.parseSocketAddressAddr(msg.getBornHost())// + ); + + System.out.printf("%-20s %s\n",// + "Store Host:",// + RemotingHelper.parseSocketAddressAddr(msg.getStoreHost())// + ); + + System.out.printf("%-20s %d\n",// + "System Flag:",// + msg.getSysFlag()// + ); + + System.out.printf("%-20s %s\n",// + "Properties:",// + msg.getProperties() != null ? msg.getProperties().toString() : ""// + ); + + System.out.printf("%-20s %s\n",// + "Message Body Path:",// + bodyTmpFilePath// + ); + } + + + @Override + public void execute(CommandLine commandLine, Options options) { + DefaultMQAdminExt defaultMQAdminExt = new DefaultMQAdminExt(); + + defaultMQAdminExt.setInstanceName(Long.toString(System.currentTimeMillis())); + + try { + final String msgId = commandLine.getOptionValue('i').trim(); + queryById(defaultMQAdminExt, msgId); + } + catch (Exception e) { + e.printStackTrace(); + } + finally { + defaultMQAdminExt.shutdown(); + } + } + + + private static String createBodyFile(MessageExt msg) throws IOException { + DataOutputStream dos = null; + + try { + String bodyTmpFilePath = "/tmp/rocketmq/msgbodys"; + File file = new File(bodyTmpFilePath); + if (!file.exists()) { + file.mkdirs(); + } + bodyTmpFilePath = bodyTmpFilePath + "/" + msg.getMsgId(); + dos = new DataOutputStream(new FileOutputStream(bodyTmpFilePath)); + dos.write(msg.getBody()); + return bodyTmpFilePath; + } + finally { + if (dos != null) + dos.close(); + } + } +} diff --git a/rocketmq-tools/src/main/java/com/alibaba/rocketmq/tools/command/message/QueryMsgByKeySubCommand.java b/rocketmq-tools/src/main/java/com/alibaba/rocketmq/tools/command/message/QueryMsgByKeySubCommand.java new file mode 100644 index 00000000..e5ad8c53 --- /dev/null +++ b/rocketmq-tools/src/main/java/com/alibaba/rocketmq/tools/command/message/QueryMsgByKeySubCommand.java @@ -0,0 +1,111 @@ +/** + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.rocketmq.tools.command.message; + +import org.apache.commons.cli.CommandLine; +import org.apache.commons.cli.Option; +import org.apache.commons.cli.Options; + +import com.alibaba.rocketmq.client.QueryResult; +import com.alibaba.rocketmq.client.exception.MQClientException; +import com.alibaba.rocketmq.common.message.MessageExt; +import com.alibaba.rocketmq.tools.admin.DefaultMQAdminExt; +import com.alibaba.rocketmq.tools.command.SubCommand; + + +/** + * 根据消息Key查询消息 + * + * @author shijia.wxr + * @since 2013-8-12 + */ +public class QueryMsgByKeySubCommand implements SubCommand { + + @Override + public String commandName() { + return "queryMsgByKey"; + } + + + @Override + public String commandDesc() { + return "Query Message by Key"; + } + + + @Override + public Options buildCommandlineOptions(Options options) { + Option opt = new Option("t", "topic", true, "topic name"); + opt.setRequired(true); + options.addOption(opt); + + opt = new Option("k", "msgKey", true, "Message Key"); + opt.setRequired(true); + options.addOption(opt); + + opt = new Option("f", "fallbackHours", true, "Fallback Hours"); + opt.setRequired(false); + options.addOption(opt); + + return options; + } + + + void queryByKey(final DefaultMQAdminExt admin, final String topic, final String key, + final long fallbackHours) throws MQClientException, InterruptedException { + admin.start(); + + long end = System.currentTimeMillis() - (fallbackHours * 60 * 60 * 1000); + long begin = end - (6 * 60 * 60 * 1000); + + QueryResult queryResult = admin.queryMessage(topic, key, 32, begin, end); + System.out.printf("%-50s %-4s %s\n",// + "#Message ID",// + "#QID",// + "#Offset"); + for (MessageExt msg : queryResult.getMessageList()) { + System.out.printf("%-50s %-4d %d\n", msg.getMsgId(), msg.getQueueId(), msg.getQueueOffset()); + } + } + + + @Override + public void execute(CommandLine commandLine, Options options) { + DefaultMQAdminExt defaultMQAdminExt = new DefaultMQAdminExt(); + + defaultMQAdminExt.setInstanceName(Long.toString(System.currentTimeMillis())); + + try { + final String topic = commandLine.getOptionValue('t').trim(); + final String key = commandLine.getOptionValue('k').trim(); + long h = 0; + if (commandLine.hasOption('f')) { + final String fallbackHours = commandLine.getOptionValue('f').trim(); + if (fallbackHours != null) { + h = Long.parseLong(fallbackHours); + } + } + + this.queryByKey(defaultMQAdminExt, topic, key, h); + } + catch (Exception e) { + e.printStackTrace(); + } + finally { + defaultMQAdminExt.shutdown(); + } + } +} diff --git a/rocketmq-tools/src/main/java/com/alibaba/rocketmq/tools/command/message/QueryMsgByOffsetSubCommand.java b/rocketmq-tools/src/main/java/com/alibaba/rocketmq/tools/command/message/QueryMsgByOffsetSubCommand.java new file mode 100644 index 00000000..7e6331c3 --- /dev/null +++ b/rocketmq-tools/src/main/java/com/alibaba/rocketmq/tools/command/message/QueryMsgByOffsetSubCommand.java @@ -0,0 +1,116 @@ +/** + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.rocketmq.tools.command.message; + +import org.apache.commons.cli.CommandLine; +import org.apache.commons.cli.Option; +import org.apache.commons.cli.Options; + +import com.alibaba.rocketmq.client.consumer.DefaultMQPullConsumer; +import com.alibaba.rocketmq.client.consumer.PullResult; +import com.alibaba.rocketmq.common.MixAll; +import com.alibaba.rocketmq.common.message.MessageQueue; +import com.alibaba.rocketmq.tools.admin.DefaultMQAdminExt; +import com.alibaba.rocketmq.tools.command.SubCommand; + + +/** + * 根据消息Offset查询消息 + * + * @author shijia.wxr + * @since 2013-8-12 + */ +public class QueryMsgByOffsetSubCommand implements SubCommand { + + @Override + public String commandName() { + return "queryMsgByOffset"; + } + + + @Override + public String commandDesc() { + return "Query Message by offset"; + } + + + @Override + public Options buildCommandlineOptions(Options options) { + Option opt = new Option("t", "topic", true, "topic name"); + opt.setRequired(true); + options.addOption(opt); + + opt = new Option("b", "brokerName", true, "Broker Name"); + opt.setRequired(true); + options.addOption(opt); + + opt = new Option("i", "queueId", true, "Queue Id"); + opt.setRequired(true); + options.addOption(opt); + + opt = new Option("o", "offset", true, "Queue Offset"); + opt.setRequired(true); + options.addOption(opt); + + return options; + } + + + @Override + public void execute(CommandLine commandLine, Options options) { + DefaultMQAdminExt defaultMQAdminExt = new DefaultMQAdminExt(); + DefaultMQPullConsumer defaultMQPullConsumer = new DefaultMQPullConsumer(MixAll.TOOLS_CONSUMER_GROUP); + + defaultMQAdminExt.setInstanceName(Long.toString(System.currentTimeMillis())); + defaultMQPullConsumer.setInstanceName(Long.toString(System.currentTimeMillis())); + + try { + String topic = commandLine.getOptionValue('t').trim(); + String brokerName = commandLine.getOptionValue('b').trim(); + String queueId = commandLine.getOptionValue('i').trim(); + String offset = commandLine.getOptionValue('o').trim(); + + MessageQueue mq = new MessageQueue(); + mq.setTopic(topic); + mq.setBrokerName(brokerName); + mq.setQueueId(Integer.parseInt(queueId)); + + defaultMQPullConsumer.start(); + + PullResult pullResult = defaultMQPullConsumer.pull(mq, "*", Long.parseLong(offset), 1); + if (pullResult != null) { + switch (pullResult.getPullStatus()) { + case FOUND: + QueryMsgByIdSubCommand.queryById(defaultMQAdminExt, pullResult.getMsgFoundList().get(0) + .getMsgId()); + break; + case NO_MATCHED_MSG: + case NO_NEW_MSG: + case OFFSET_ILLEGAL: + default: + break; + } + } + } + catch (Exception e) { + e.printStackTrace(); + } + finally { + defaultMQPullConsumer.shutdown(); + defaultMQAdminExt.shutdown(); + } + } +} diff --git a/rocketmq-tools/src/main/java/com/alibaba/rocketmq/tools/command/namesrv/DeleteKvConfigCommand.java b/rocketmq-tools/src/main/java/com/alibaba/rocketmq/tools/command/namesrv/DeleteKvConfigCommand.java new file mode 100644 index 00000000..d758a7bc --- /dev/null +++ b/rocketmq-tools/src/main/java/com/alibaba/rocketmq/tools/command/namesrv/DeleteKvConfigCommand.java @@ -0,0 +1,80 @@ +/** + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.rocketmq.tools.command.namesrv; + +import org.apache.commons.cli.CommandLine; +import org.apache.commons.cli.Option; +import org.apache.commons.cli.Options; + +import com.alibaba.rocketmq.tools.admin.DefaultMQAdminExt; +import com.alibaba.rocketmq.tools.command.SubCommand; + + +/** + * 删除 KV 配置信息 + * + * @author: manhong.yqd + * @since: 13-8-29 + */ +public class DeleteKvConfigCommand implements SubCommand { + @Override + public String commandName() { + return "deleteKvConfig"; + } + + + @Override + public String commandDesc() { + return "delete KV config."; + } + + + @Override + public Options buildCommandlineOptions(Options options) { + Option opt = new Option("s", "namespace", true, "set the namespace"); + opt.setRequired(true); + options.addOption(opt); + + opt = new Option("k", "key", true, "set the key name"); + opt.setRequired(true); + options.addOption(opt); + return options; + } + + + @Override + public void execute(CommandLine commandLine, Options options) { + DefaultMQAdminExt defaultMQAdminExt = new DefaultMQAdminExt(); + defaultMQAdminExt.setInstanceName(Long.toString(System.currentTimeMillis())); + try { + // namespace + String namespace = commandLine.getOptionValue('s').trim(); + // key name + String key = commandLine.getOptionValue('k').trim(); + + defaultMQAdminExt.start(); + defaultMQAdminExt.deleteKvConfig(namespace, key); + System.out.printf("delete kv config from namespace success.\n"); + return; + } + catch (Exception e) { + e.printStackTrace(); + } + finally { + defaultMQAdminExt.shutdown(); + } + } +} diff --git a/rocketmq-tools/src/main/java/com/alibaba/rocketmq/tools/command/namesrv/DeleteProjectGroupCommand.java b/rocketmq-tools/src/main/java/com/alibaba/rocketmq/tools/command/namesrv/DeleteProjectGroupCommand.java new file mode 100644 index 00000000..52b610dd --- /dev/null +++ b/rocketmq-tools/src/main/java/com/alibaba/rocketmq/tools/command/namesrv/DeleteProjectGroupCommand.java @@ -0,0 +1,90 @@ +/** + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.rocketmq.tools.command.namesrv; + +import org.apache.commons.cli.CommandLine; +import org.apache.commons.cli.Option; +import org.apache.commons.cli.Options; + +import com.alibaba.rocketmq.common.MixAll; +import com.alibaba.rocketmq.common.namesrv.NamesrvUtil; +import com.alibaba.rocketmq.tools.admin.DefaultMQAdminExt; +import com.alibaba.rocketmq.tools.command.SubCommand; + + +/** + * 删除 project group 配置信息 + * + * @author: manhong.yqd + * @since: 13-8-29 + */ +public class DeleteProjectGroupCommand implements SubCommand { + @Override + public String commandName() { + return "deleteProjectGroup"; + } + + + @Override + public String commandDesc() { + return "delete project group by server ip."; + } + + + @Override + public Options buildCommandlineOptions(Options options) { + Option opt = new Option("i", "ip", true, "set the server ip"); + opt.setRequired(false); + options.addOption(opt); + + opt = new Option("p", "project", true, "set the project group"); + opt.setRequired(false); + options.addOption(opt); + return options; + } + + + @Override + public void execute(CommandLine commandLine, Options options) { + DefaultMQAdminExt defaultMQAdminExt = new DefaultMQAdminExt(); + defaultMQAdminExt.setInstanceName(Long.toString(System.currentTimeMillis())); + try { + String namespace = NamesrvUtil.NAMESPACE_PROJECT_CONFIG; + + if (commandLine.hasOption("i")) { + String ip = commandLine.getOptionValue('i').trim(); + defaultMQAdminExt.start(); + defaultMQAdminExt.deleteKvConfig(namespace, ip); + System.out.printf("delete project group from namespace by server ip success.\n"); + } + else if (commandLine.hasOption("p")) { + String project = commandLine.getOptionValue('p').trim(); + defaultMQAdminExt.start(); + defaultMQAdminExt.deleteIpsByProjectGroup(project); + System.out.printf("delete all server ip from namespace by project group success.\n"); + } + else { + MixAll.printCommandLineHelp("mqadmin " + this.commandName(), options); + } + } + catch (Exception e) { + e.printStackTrace(); + } + finally { + defaultMQAdminExt.shutdown(); + } + } +} diff --git a/rocketmq-tools/src/main/java/com/alibaba/rocketmq/tools/command/namesrv/GetProjectGroupCommand.java b/rocketmq-tools/src/main/java/com/alibaba/rocketmq/tools/command/namesrv/GetProjectGroupCommand.java new file mode 100644 index 00000000..742b0c1c --- /dev/null +++ b/rocketmq-tools/src/main/java/com/alibaba/rocketmq/tools/command/namesrv/GetProjectGroupCommand.java @@ -0,0 +1,93 @@ +/** + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.rocketmq.tools.command.namesrv; + +import org.apache.commons.cli.CommandLine; +import org.apache.commons.cli.Option; +import org.apache.commons.cli.Options; + +import com.alibaba.rocketmq.common.MixAll; +import com.alibaba.rocketmq.common.UtilAll; +import com.alibaba.rocketmq.tools.admin.DefaultMQAdminExt; +import com.alibaba.rocketmq.tools.command.SubCommand; + + +/** + * 取得 project group 配置信息 + * + * @author: manhong.yqd + * @since: 13-8-29 + */ +public class GetProjectGroupCommand implements SubCommand { + @Override + public String commandName() { + return "getProjectGroup"; + } + + + @Override + public String commandDesc() { + return "get project group by server ip or project group name."; + } + + + @Override + public Options buildCommandlineOptions(Options options) { + Option opt = new Option("i", "ip", true, "set the server ip"); + opt.setRequired(false); + options.addOption(opt); + + opt = new Option("p", "project", true, "set the project group"); + opt.setRequired(false); + options.addOption(opt); + return options; + } + + + @Override + public void execute(CommandLine commandLine, Options options) { + DefaultMQAdminExt defaultMQAdminExt = new DefaultMQAdminExt(); + defaultMQAdminExt.setInstanceName(Long.toString(System.currentTimeMillis())); + try { + if (commandLine.hasOption("i")) { + String ip = commandLine.getOptionValue('i').trim(); + defaultMQAdminExt.start(); + String project = defaultMQAdminExt.getProjectGroupByIp(ip); + System.out.printf("ip=%s, projectGroup=%s\n", ip, project); + } + else if (commandLine.hasOption("p")) { + String project = commandLine.getOptionValue('p').trim(); + defaultMQAdminExt.start(); + String ips = defaultMQAdminExt.getIpsByProjectGroup(project); + if (UtilAll.isBlank(ips)) { + System.out.printf("No ip in project group[%s]\n", project); + } + else { + System.out.printf("projectGroup=%s, ips=%s\n", project, ips); + } + } + else { + MixAll.printCommandLineHelp("mqadmin " + this.commandName(), options); + } + } + catch (Exception e) { + e.printStackTrace(); + } + finally { + defaultMQAdminExt.shutdown(); + } + } +} diff --git a/rocketmq-tools/src/main/java/com/alibaba/rocketmq/tools/command/namesrv/UpdateKvConfigCommand.java b/rocketmq-tools/src/main/java/com/alibaba/rocketmq/tools/command/namesrv/UpdateKvConfigCommand.java new file mode 100644 index 00000000..cd3b720f --- /dev/null +++ b/rocketmq-tools/src/main/java/com/alibaba/rocketmq/tools/command/namesrv/UpdateKvConfigCommand.java @@ -0,0 +1,86 @@ +/** + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.rocketmq.tools.command.namesrv; + +import org.apache.commons.cli.CommandLine; +import org.apache.commons.cli.Option; +import org.apache.commons.cli.Options; + +import com.alibaba.rocketmq.tools.admin.DefaultMQAdminExt; +import com.alibaba.rocketmq.tools.command.SubCommand; + + +/** + * 添加或者更新 KV 配置信息 + * + * @author: manhong.yqd + * @since: 13-8-29 + */ +public class UpdateKvConfigCommand implements SubCommand { + @Override + public String commandName() { + return "updateKvConfig"; + } + + + @Override + public String commandDesc() { + return "create or update KV config."; + } + + + @Override + public Options buildCommandlineOptions(Options options) { + Option opt = new Option("s", "namespace", true, "set the namespace"); + opt.setRequired(true); + options.addOption(opt); + + opt = new Option("k", "key", true, "set the key name"); + opt.setRequired(true); + options.addOption(opt); + + opt = new Option("v", "value", true, "set the key value"); + opt.setRequired(true); + options.addOption(opt); + return options; + } + + + @Override + public void execute(CommandLine commandLine, Options options) { + DefaultMQAdminExt defaultMQAdminExt = new DefaultMQAdminExt(); + defaultMQAdminExt.setInstanceName(Long.toString(System.currentTimeMillis())); + try { + // namespace + String namespace = commandLine.getOptionValue('s').trim(); + // key name + String key = commandLine.getOptionValue('k').trim(); + // key name + String value = commandLine.getOptionValue('v').trim(); + + defaultMQAdminExt.start(); + defaultMQAdminExt.createAndUpdateKvConfig(namespace, key, value); + System.out.printf("create or update kv config to namespace success.\n"); + return; + } + catch (Exception e) { + e.printStackTrace(); + } + finally { + defaultMQAdminExt.shutdown(); + } + } +} diff --git a/rocketmq-tools/src/main/java/com/alibaba/rocketmq/tools/command/namesrv/UpdateProjectGroupCommand.java b/rocketmq-tools/src/main/java/com/alibaba/rocketmq/tools/command/namesrv/UpdateProjectGroupCommand.java new file mode 100644 index 00000000..ce180bd5 --- /dev/null +++ b/rocketmq-tools/src/main/java/com/alibaba/rocketmq/tools/command/namesrv/UpdateProjectGroupCommand.java @@ -0,0 +1,80 @@ +/** + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.rocketmq.tools.command.namesrv; + +import org.apache.commons.cli.CommandLine; +import org.apache.commons.cli.Option; +import org.apache.commons.cli.Options; + +import com.alibaba.rocketmq.common.namesrv.NamesrvUtil; +import com.alibaba.rocketmq.tools.admin.DefaultMQAdminExt; +import com.alibaba.rocketmq.tools.command.SubCommand; + + +/** + * 添加或者更新 project group 配置信息 + * + * @author: manhong.yqd + * @since: 13-8-29 + */ +public class UpdateProjectGroupCommand implements SubCommand { + @Override + public String commandName() { + return "updateProjectGroup"; + } + + + @Override + public String commandDesc() { + return "create or update project group by server ip."; + } + + + @Override + public Options buildCommandlineOptions(Options options) { + Option opt = new Option("i", "ip", true, "set the server ip"); + opt.setRequired(true); + options.addOption(opt); + + opt = new Option("p", "project", true, "set the project group"); + opt.setRequired(true); + options.addOption(opt); + return options; + } + + + @Override + public void execute(CommandLine commandLine, Options options) { + DefaultMQAdminExt defaultMQAdminExt = new DefaultMQAdminExt(); + defaultMQAdminExt.setInstanceName(Long.toString(System.currentTimeMillis())); + try { + String namespace = NamesrvUtil.NAMESPACE_PROJECT_CONFIG; + String ip = commandLine.getOptionValue('i').trim(); + String project = commandLine.getOptionValue('p').trim(); + + defaultMQAdminExt.start(); + defaultMQAdminExt.createAndUpdateKvConfig(namespace, ip, project); + System.out.printf("create or update kv config to namespace success.\n"); + return; + } + catch (Exception e) { + e.printStackTrace(); + } + finally { + defaultMQAdminExt.shutdown(); + } + } +} diff --git a/rocketmq-tools/src/main/java/com/alibaba/rocketmq/tools/command/namesrv/WipeWritePermSubCommand.java b/rocketmq-tools/src/main/java/com/alibaba/rocketmq/tools/command/namesrv/WipeWritePermSubCommand.java new file mode 100644 index 00000000..07493706 --- /dev/null +++ b/rocketmq-tools/src/main/java/com/alibaba/rocketmq/tools/command/namesrv/WipeWritePermSubCommand.java @@ -0,0 +1,95 @@ +/** + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.rocketmq.tools.command.namesrv; + +import java.util.List; + +import org.apache.commons.cli.CommandLine; +import org.apache.commons.cli.Option; +import org.apache.commons.cli.Options; + +import com.alibaba.rocketmq.tools.admin.DefaultMQAdminExt; +import com.alibaba.rocketmq.tools.command.SubCommand; + + +/** + * 从所有Name Server上清除特定Broker的先权限 + * + * @author shijia.wxr + * @since 2013-8-6 + */ +public class WipeWritePermSubCommand implements SubCommand { + + @Override + public String commandName() { + return "wipeWritePerm"; + } + + + @Override + public String commandDesc() { + return "Wipe write perm of broker in all name server"; + } + + + @Override + public Options buildCommandlineOptions(Options options) { + Option opt = new Option("b", "brokerName", true, "broker name"); + opt.setRequired(true); + options.addOption(opt); + return options; + } + + + @Override + public void execute(CommandLine commandLine, Options options) { + DefaultMQAdminExt defaultMQAdminExt = new DefaultMQAdminExt(); + + defaultMQAdminExt.setInstanceName(Long.toString(System.currentTimeMillis())); + + try { + defaultMQAdminExt.start(); + String brokerName = commandLine.getOptionValue('b').trim(); + List namesrvList = defaultMQAdminExt.getNameServerAddressList(); + if (namesrvList != null) { + for (String namesrvAddr : namesrvList) { + try { + int wipeTopicCount = defaultMQAdminExt.wipeWritePermOfBroker(namesrvAddr, brokerName); + System.out.printf("wipe write perm of broker[%s] in name server[%s] OK, %d\n",// + brokerName,// + namesrvAddr,// + wipeTopicCount// + ); + } + catch (Exception e) { + System.out.printf("wipe write perm of broker[%s] in name server[%s] Failed\n",// + brokerName,// + namesrvAddr// + ); + + e.printStackTrace(); + } + } + } + } + catch (Exception e) { + e.printStackTrace(); + } + finally { + defaultMQAdminExt.shutdown(); + } + } +} diff --git a/rocketmq-tools/src/main/java/com/alibaba/rocketmq/tools/command/offset/GetConsumerStatusCommand.java b/rocketmq-tools/src/main/java/com/alibaba/rocketmq/tools/command/offset/GetConsumerStatusCommand.java new file mode 100644 index 00000000..2ca76f52 --- /dev/null +++ b/rocketmq-tools/src/main/java/com/alibaba/rocketmq/tools/command/offset/GetConsumerStatusCommand.java @@ -0,0 +1,113 @@ +package com.alibaba.rocketmq.tools.command.offset; + +import java.util.Iterator; +import java.util.Map; + +import org.apache.commons.cli.CommandLine; +import org.apache.commons.cli.Option; +import org.apache.commons.cli.Options; +import org.apache.commons.cli.PosixParser; + +import com.alibaba.rocketmq.common.MixAll; +import com.alibaba.rocketmq.common.UtilAll; +import com.alibaba.rocketmq.common.message.MessageQueue; +import com.alibaba.rocketmq.tools.admin.DefaultMQAdminExt; +import com.alibaba.rocketmq.tools.command.SubCommand; + + +/** + * 根据时间来设置消费进度,设置之前要关闭这个订阅组的所有consumer,设置完再启动,方可生效。 + * + * @author: manhong.yqd + * @since: 13-9-12 + */ +public class GetConsumerStatusCommand implements SubCommand { + @Override + public String commandName() { + return "getConsumerStatus"; + } + + + @Override + public String commandDesc() { + return "get consumer status from client."; + } + + + @Override + public Options buildCommandlineOptions(Options options) { + Option opt = new Option("g", "group", true, "set the consumer group"); + opt.setRequired(true); + options.addOption(opt); + + opt = new Option("t", "topic", true, "set the topic"); + opt.setRequired(true); + options.addOption(opt); + + opt = new Option("i", "originClientId", true, "set the consumer clientId"); + opt.setRequired(false); + options.addOption(opt); + + return options; + } + + + @Override + public void execute(CommandLine commandLine, Options options) { + DefaultMQAdminExt defaultMQAdminExt = new DefaultMQAdminExt(); + defaultMQAdminExt.setInstanceName(Long.toString(System.currentTimeMillis())); + try { + String group = commandLine.getOptionValue("g").trim(); + String topic = commandLine.getOptionValue("t").trim(); + String originClientId = ""; + if (commandLine.hasOption("i")) { + originClientId = commandLine.getOptionValue("i").trim(); + } + defaultMQAdminExt.start(); + + Map> consumerStatusTable = + defaultMQAdminExt.getConsumeStatus(topic, group, originClientId); + System.out.printf("get consumer status from client. group=%s, topic=%s, originClientId=%s\n", + group, topic, originClientId); + + System.out.printf("%-50s %-15s %-15s %-20s\n",// + "#clientId",// + "#brokerName", // + "#queueId",// + "#offset"); + + Iterator clientIterator = consumerStatusTable.keySet().iterator(); + while (clientIterator.hasNext()) { + String clientId = clientIterator.next(); + Map mqTable = consumerStatusTable.get(clientId); + Iterator mqIterator = mqTable.keySet().iterator(); + while (mqIterator.hasNext()) { + MessageQueue mq = mqIterator.next(); + System.out.printf("%-50s %-15s %-15d %-20d\n",// + UtilAll.frontStringAtLeast(clientId, 50),// + mq.getBrokerName(),// + mq.getQueueId(),// + mqTable.get(mq)); + } + } + } + catch (Exception e) { + e.printStackTrace(); + } + finally { + defaultMQAdminExt.shutdown(); + } + } + + + public static void main(String[] args) { + System.setProperty(MixAll.NAMESRV_ADDR_PROPERTY, "10.232.26.122:9876"); + GetConsumerStatusCommand cmd = new GetConsumerStatusCommand(); + Options options = MixAll.buildCommandlineOptions(new Options()); + String[] subargs = new String[] { "-t qatest_TopicTest", "-g qatest_consumer_broadcast" }; + final CommandLine commandLine = + MixAll.parseCmdLine("mqadmin " + cmd.commandName(), subargs, + cmd.buildCommandlineOptions(options), new PosixParser()); + cmd.execute(commandLine, options); + } +} diff --git a/rocketmq-tools/src/main/java/com/alibaba/rocketmq/tools/command/offset/ResetOffsetByTimeCommand.java b/rocketmq-tools/src/main/java/com/alibaba/rocketmq/tools/command/offset/ResetOffsetByTimeCommand.java new file mode 100644 index 00000000..12a2d12c --- /dev/null +++ b/rocketmq-tools/src/main/java/com/alibaba/rocketmq/tools/command/offset/ResetOffsetByTimeCommand.java @@ -0,0 +1,125 @@ +package com.alibaba.rocketmq.tools.command.offset; + +import java.util.Iterator; +import java.util.Map; + +import org.apache.commons.cli.CommandLine; +import org.apache.commons.cli.Option; +import org.apache.commons.cli.Options; +import org.apache.commons.cli.PosixParser; + +import com.alibaba.rocketmq.common.MixAll; +import com.alibaba.rocketmq.common.UtilAll; +import com.alibaba.rocketmq.common.message.MessageQueue; +import com.alibaba.rocketmq.tools.admin.DefaultMQAdminExt; +import com.alibaba.rocketmq.tools.command.SubCommand; + + +/** + * 根据时间来设置消费进度,设置之前要关闭这个订阅组的所有consumer,客户端不需要重启。 + * + * @author: manhong.yqd + * @since: 13-9-12 + */ +public class ResetOffsetByTimeCommand implements SubCommand { + @Override + public String commandName() { + return "resetOffsetByTime"; + } + + + @Override + public String commandDesc() { + return "Reset consumer offset by timestamp(without client restart)."; + } + + + @Override + public Options buildCommandlineOptions(Options options) { + Option opt = new Option("g", "group", true, "set the consumer group"); + opt.setRequired(true); + options.addOption(opt); + + opt = new Option("t", "topic", true, "set the topic"); + opt.setRequired(true); + options.addOption(opt); + + opt = + new Option("s", "timestamp", true, + "set the timestamp[currentTimeMillis|yyyy-MM-dd#HH:mm:ss:SSS]"); + opt.setRequired(true); + options.addOption(opt); + + opt = new Option("f", "force", true, "set the force rollback by timestamp switch[true|false]"); + opt.setRequired(false); + options.addOption(opt); + return options; + } + + + @Override + public void execute(CommandLine commandLine, Options options) { + DefaultMQAdminExt defaultMQAdminExt = new DefaultMQAdminExt(); + defaultMQAdminExt.setInstanceName(Long.toString(System.currentTimeMillis())); + try { + String group = commandLine.getOptionValue("g").trim(); + String topic = commandLine.getOptionValue("t").trim(); + String timeStampStr = commandLine.getOptionValue("s").trim(); + long timestamp = 0; + try { + // 直接输入 long 类型的 timestamp + timestamp = Long.valueOf(timeStampStr); + } + catch (NumberFormatException e) { + // 输入的为日期格式,精确到毫秒 + timestamp = UtilAll.parseDate(timeStampStr, UtilAll.yyyy_MM_dd_HH_mm_ss_SSS).getTime(); + } + + boolean force = true; + if (commandLine.hasOption('f')) { + force = Boolean.valueOf(commandLine.getOptionValue("f").trim()); + } + + defaultMQAdminExt.start(); + Map offsetTable = + defaultMQAdminExt.resetOffsetByTimestamp(topic, group, timestamp, force); + System.out + .printf( + "rollback consumer offset by specified group[%s], topic[%s], force[%s], timestamp(string)[%s], timestamp(long)[%s]\n", + group, topic, force, timeStampStr, timestamp); + + System.out.printf("%-40s %-40s %-40s\n",// + "#brokerName",// + "#queueId",// + "#offset"); + + Iterator> iterator = offsetTable.entrySet().iterator(); + while (iterator.hasNext()) { + Map.Entry entry = iterator.next(); + System.out.printf("%-40s %-40d %-40d\n",// + UtilAll.frontStringAtLeast(entry.getKey().getBrokerName(), 32),// + entry.getKey().getQueueId(),// + entry.getValue()); + } + } + catch (Exception e) { + e.printStackTrace(); + } + finally { + defaultMQAdminExt.shutdown(); + } + } + + + public static void main(String[] args) { + System.setProperty(MixAll.NAMESRV_ADDR_PROPERTY, "10.232.26.122:9876"); + ResetOffsetByTimeCommand cmd = new ResetOffsetByTimeCommand(); + Options options = MixAll.buildCommandlineOptions(new Options()); + String[] subargs = + new String[] { "-t qatest_TopicTest", "-g qatest_consumer", "-s 1389098416742", "-f true" }; + final CommandLine commandLine = + MixAll.parseCmdLine("mqadmin " + cmd.commandName(), subargs, + cmd.buildCommandlineOptions(options), new PosixParser()); + cmd.execute(commandLine, options); + } +} diff --git a/rocketmq-tools/src/main/java/com/alibaba/rocketmq/tools/command/offset/ResetOffsetByTimeOldCommand.java b/rocketmq-tools/src/main/java/com/alibaba/rocketmq/tools/command/offset/ResetOffsetByTimeOldCommand.java new file mode 100644 index 00000000..898fb774 --- /dev/null +++ b/rocketmq-tools/src/main/java/com/alibaba/rocketmq/tools/command/offset/ResetOffsetByTimeOldCommand.java @@ -0,0 +1,115 @@ +package com.alibaba.rocketmq.tools.command.offset; + +import java.util.List; + +import org.apache.commons.cli.CommandLine; +import org.apache.commons.cli.Option; +import org.apache.commons.cli.Options; + +import com.alibaba.rocketmq.common.UtilAll; +import com.alibaba.rocketmq.common.admin.RollbackStats; +import com.alibaba.rocketmq.tools.admin.DefaultMQAdminExt; +import com.alibaba.rocketmq.tools.command.SubCommand; + + +/** + * 根据时间来设置消费进度,设置之前要关闭这个订阅组的所有consumer,设置完再启动,方可生效。 + * + * @author: manhong.yqd + * @since: 13-9-12 + */ +public class ResetOffsetByTimeOldCommand implements SubCommand { + @Override + public String commandName() { + return "resetOffsetByTimeOld"; + } + + + @Override + public String commandDesc() { + return "Reset consumer offset by timestamp(execute this command required client restart)."; + } + + + @Override + public Options buildCommandlineOptions(Options options) { + Option opt = new Option("g", "group", true, "set the consumer group"); + opt.setRequired(true); + options.addOption(opt); + + opt = new Option("t", "topic", true, "set the topic"); + opt.setRequired(true); + options.addOption(opt); + + opt = + new Option("s", "timestamp", true, + "set the timestamp[currentTimeMillis|yyyy-MM-dd#HH:mm:ss:SSS]"); + opt.setRequired(true); + options.addOption(opt); + + opt = new Option("f", "force", true, "set the force rollback by timestamp switch[true|false]"); + opt.setRequired(false); + options.addOption(opt); + return options; + } + + + @Override + public void execute(CommandLine commandLine, Options options) { + DefaultMQAdminExt defaultMQAdminExt = new DefaultMQAdminExt(); + defaultMQAdminExt.setInstanceName(Long.toString(System.currentTimeMillis())); + try { + String consumerGroup = commandLine.getOptionValue("g").trim(); + String topic = commandLine.getOptionValue("t").trim(); + String timeStampStr = commandLine.getOptionValue("s").trim(); + long timestamp = 0; + try { + // 直接输入 long 类型的 timestamp + timestamp = Long.valueOf(timeStampStr); + } + catch (NumberFormatException e) { + // 输入的为日期格式,精确到毫秒 + timestamp = UtilAll.parseDate(timeStampStr, UtilAll.yyyy_MM_dd_HH_mm_ss_SSS).getTime(); + } + + boolean force = true; + if (commandLine.hasOption('f')) { + force = Boolean.valueOf(commandLine.getOptionValue("f").trim()); + } + + defaultMQAdminExt.start(); + List rollbackStatsList = + defaultMQAdminExt.resetOffsetByTimestampOld(consumerGroup, topic, timestamp, force); + System.out + .printf( + "rollback consumer offset by specified consumerGroup[%s], topic[%s], force[%s], timestamp(string)[%s], timestamp(long)[%s]\n", + consumerGroup, topic, force, timeStampStr, timestamp); + + System.out.printf("%-20s %-20s %-20s %-20s %-20s %-20s\n",// + "#brokerName",// + "#queueId",// + "#brokerOffset",// + "#consumerOffset",// + "#timestampOffset",// + "#rollbackOffset" // + ); + + for (RollbackStats rollbackStats : rollbackStatsList) { + System.out.printf("%-20s %-20d %-20d %-20d %-20d %-20d\n",// + UtilAll.frontStringAtLeast(rollbackStats.getBrokerName(), 32),// + rollbackStats.getQueueId(),// + rollbackStats.getBrokerOffset(),// + rollbackStats.getConsumerOffset(),// + rollbackStats.getTimestampOffset(),// + rollbackStats.getRollbackOffset() // + ); + } + } + catch (Exception e) { + e.printStackTrace(); + } + finally { + defaultMQAdminExt.shutdown(); + } + } +} diff --git a/rocketmq-tools/src/main/java/com/alibaba/rocketmq/tools/command/topic/DeleteTopicSubCommand.java b/rocketmq-tools/src/main/java/com/alibaba/rocketmq/tools/command/topic/DeleteTopicSubCommand.java new file mode 100644 index 00000000..1977b42d --- /dev/null +++ b/rocketmq-tools/src/main/java/com/alibaba/rocketmq/tools/command/topic/DeleteTopicSubCommand.java @@ -0,0 +1,101 @@ +/** + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.rocketmq.tools.command.topic; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; + +import org.apache.commons.cli.CommandLine; +import org.apache.commons.cli.Option; +import org.apache.commons.cli.Options; + +import com.alibaba.rocketmq.common.MixAll; +import com.alibaba.rocketmq.tools.admin.DefaultMQAdminExt; +import com.alibaba.rocketmq.tools.command.CommandUtil; +import com.alibaba.rocketmq.tools.command.SubCommand; + + +/** + * 删除Topic配置命令 + * + * @author manhong.yqd + * @since 2013-8-21 + */ +public class DeleteTopicSubCommand implements SubCommand { + @Override + public String commandName() { + return "deleteTopic"; + } + + + @Override + public String commandDesc() { + return "delete topic from broker and NameServer."; + } + + + @Override + public Options buildCommandlineOptions(Options options) { + Option opt = new Option("t", "topic", true, "topic name"); + opt.setRequired(true); + options.addOption(opt); + + opt = new Option("c", "clusterName", true, "delete topic from which cluster"); + opt.setRequired(true); + options.addOption(opt); + + return options; + } + + + @Override + public void execute(CommandLine commandLine, Options options) { + DefaultMQAdminExt adminExt = new DefaultMQAdminExt(); + adminExt.setInstanceName(Long.toString(System.currentTimeMillis())); + try { + String topic = commandLine.getOptionValue('t').trim(); + + if (commandLine.hasOption('c')) { + String clusterName = commandLine.getOptionValue('c').trim(); + + adminExt.start(); + // 删除 broker 上的 topic 信息 + Set masterSet = CommandUtil.fetchMasterAddrByClusterName(adminExt, clusterName); + adminExt.deleteTopicInBroker(masterSet, topic); + System.out.printf("delete topic [%s] from cluster [%s] success.\n", topic, clusterName); + + // 删除 NameServer 上的 topic 信息 + Set nameServerSet = null; + if (commandLine.hasOption('n')) { + String[] ns = commandLine.getOptionValue('n').trim().split(";"); + nameServerSet = new HashSet(Arrays.asList(ns)); + } + adminExt.deleteTopicInNameServer(nameServerSet, topic); + System.out.printf("delete topic [%s] from NameServer success.\n", topic); + return; + } + + MixAll.printCommandLineHelp("mqadmin " + this.commandName(), options); + } + catch (Exception e) { + e.printStackTrace(); + } + finally { + adminExt.shutdown(); + } + } +} diff --git a/rocketmq-tools/src/main/java/com/alibaba/rocketmq/tools/command/topic/TopicListSubCommand.java b/rocketmq-tools/src/main/java/com/alibaba/rocketmq/tools/command/topic/TopicListSubCommand.java new file mode 100644 index 00000000..00189f0b --- /dev/null +++ b/rocketmq-tools/src/main/java/com/alibaba/rocketmq/tools/command/topic/TopicListSubCommand.java @@ -0,0 +1,73 @@ +/** + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.rocketmq.tools.command.topic; + +import org.apache.commons.cli.CommandLine; +import org.apache.commons.cli.Options; + +import com.alibaba.rocketmq.common.protocol.body.TopicList; +import com.alibaba.rocketmq.tools.admin.DefaultMQAdminExt; +import com.alibaba.rocketmq.tools.command.SubCommand; + + +/** + * 查看Topic统计信息,包括offset、最后更新时间 + * + * @author shijia.wxr + * @since 2013-8-3 + */ +public class TopicListSubCommand implements SubCommand { + + @Override + public String commandName() { + return "topicList"; + } + + + @Override + public String commandDesc() { + return "Fetch all topic list from name server"; + } + + + @Override + public Options buildCommandlineOptions(Options options) { + return options; + } + + + @Override + public void execute(final CommandLine commandLine, final Options options) { + DefaultMQAdminExt defaultMQAdminExt = new DefaultMQAdminExt(); + + defaultMQAdminExt.setInstanceName(Long.toString(System.currentTimeMillis())); + + try { + defaultMQAdminExt.start(); + + TopicList topicList = defaultMQAdminExt.fetchAllTopicList(); + for (String topic : topicList.getTopicList()) { + System.out.println(topic); + } + } + catch (Exception e) { + e.printStackTrace(); + } + finally { + defaultMQAdminExt.shutdown(); + } + } +} diff --git a/rocketmq-tools/src/main/java/com/alibaba/rocketmq/tools/command/topic/TopicRouteSubCommand.java b/rocketmq-tools/src/main/java/com/alibaba/rocketmq/tools/command/topic/TopicRouteSubCommand.java new file mode 100644 index 00000000..3864abdc --- /dev/null +++ b/rocketmq-tools/src/main/java/com/alibaba/rocketmq/tools/command/topic/TopicRouteSubCommand.java @@ -0,0 +1,78 @@ +/** + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.rocketmq.tools.command.topic; + +import org.apache.commons.cli.CommandLine; +import org.apache.commons.cli.Option; +import org.apache.commons.cli.Options; + +import com.alibaba.rocketmq.common.protocol.route.TopicRouteData; +import com.alibaba.rocketmq.tools.admin.DefaultMQAdminExt; +import com.alibaba.rocketmq.tools.command.SubCommand; + + +/** + * 查看Topic路由信息 + * + * @author shijia.wxr + * @since 2013-8-3 + */ +public class TopicRouteSubCommand implements SubCommand { + + @Override + public String commandName() { + return "topicRoute"; + } + + + @Override + public String commandDesc() { + return "Examine topic route info"; + } + + + @Override + public Options buildCommandlineOptions(Options options) { + Option opt = new Option("t", "topic", true, "topic name"); + opt.setRequired(true); + options.addOption(opt); + + return options; + } + + + @Override + public void execute(final CommandLine commandLine, final Options options) { + DefaultMQAdminExt defaultMQAdminExt = new DefaultMQAdminExt(); + + defaultMQAdminExt.setInstanceName(Long.toString(System.currentTimeMillis())); + + try { + defaultMQAdminExt.start(); + + String topic = commandLine.getOptionValue('t').trim(); + TopicRouteData topicRouteData = defaultMQAdminExt.examineTopicRouteInfo(topic); + String json = topicRouteData.toJson(true); + System.out.println(json); + } + catch (Exception e) { + e.printStackTrace(); + } + finally { + defaultMQAdminExt.shutdown(); + } + } +} diff --git a/rocketmq-tools/src/main/java/com/alibaba/rocketmq/tools/command/topic/TopicStatsSubCommand.java b/rocketmq-tools/src/main/java/com/alibaba/rocketmq/tools/command/topic/TopicStatsSubCommand.java new file mode 100644 index 00000000..a4faf90a --- /dev/null +++ b/rocketmq-tools/src/main/java/com/alibaba/rocketmq/tools/command/topic/TopicStatsSubCommand.java @@ -0,0 +1,112 @@ +/** + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.rocketmq.tools.command.topic; + +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; + +import org.apache.commons.cli.CommandLine; +import org.apache.commons.cli.Option; +import org.apache.commons.cli.Options; + +import com.alibaba.rocketmq.common.UtilAll; +import com.alibaba.rocketmq.common.admin.TopicOffset; +import com.alibaba.rocketmq.common.admin.TopicStatsTable; +import com.alibaba.rocketmq.common.message.MessageQueue; +import com.alibaba.rocketmq.tools.admin.DefaultMQAdminExt; +import com.alibaba.rocketmq.tools.command.SubCommand; + + +/** + * 查看Topic统计信息,包括offset、最后更新时间 + * + * @author shijia.wxr + * @since 2013-8-3 + */ +public class TopicStatsSubCommand implements SubCommand { + + @Override + public String commandName() { + return "topicStats"; + } + + + @Override + public String commandDesc() { + return "Examine topic stats info"; + } + + + @Override + public Options buildCommandlineOptions(Options options) { + Option opt = new Option("t", "topic", true, "topic name"); + opt.setRequired(true); + options.addOption(opt); + + return options; + } + + + @Override + public void execute(final CommandLine commandLine, final Options options) { + DefaultMQAdminExt defaultMQAdminExt = new DefaultMQAdminExt(); + + defaultMQAdminExt.setInstanceName(Long.toString(System.currentTimeMillis())); + + try { + defaultMQAdminExt.start(); + + String topic = commandLine.getOptionValue('t').trim(); + TopicStatsTable topicStatsTable = defaultMQAdminExt.examineTopicStats(topic); + + List mqList = new LinkedList(); + mqList.addAll(topicStatsTable.getOffsetTable().keySet()); + Collections.sort(mqList); + + System.out.printf("%-32s %-4s %-20s %-20s %s\n",// + "#Broker Name",// + "#QID",// + "#Min Offset",// + "#Max Offset",// + "#Last Updated" // + ); + + for (MessageQueue mq : mqList) { + TopicOffset topicOffset = topicStatsTable.getOffsetTable().get(mq); + + String humanTimestamp = ""; + if (topicOffset.getLastUpdateTimestamp() > 0) { + humanTimestamp = UtilAll.timeMillisToHumanString2(topicOffset.getLastUpdateTimestamp()); + } + + System.out.printf("%-32s %-4d %-20d %-20d %s\n",// + UtilAll.frontStringAtLeast(mq.getBrokerName(), 32),// + mq.getQueueId(),// + topicOffset.getMinOffset(),// + topicOffset.getMaxOffset(),// + humanTimestamp // + ); + } + } + catch (Exception e) { + e.printStackTrace(); + } + finally { + defaultMQAdminExt.shutdown(); + } + } +} diff --git a/rocketmq-tools/src/main/java/com/alibaba/rocketmq/tools/command/topic/UpdateTopicSubCommand.java b/rocketmq-tools/src/main/java/com/alibaba/rocketmq/tools/command/topic/UpdateTopicSubCommand.java new file mode 100644 index 00000000..2a35a225 --- /dev/null +++ b/rocketmq-tools/src/main/java/com/alibaba/rocketmq/tools/command/topic/UpdateTopicSubCommand.java @@ -0,0 +1,142 @@ +/** + * Copyright (C) 2010-2013 Alibaba Group Holding Limited + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.rocketmq.tools.command.topic; + +import java.util.Set; + +import org.apache.commons.cli.CommandLine; +import org.apache.commons.cli.Option; +import org.apache.commons.cli.Options; + +import com.alibaba.rocketmq.common.MixAll; +import com.alibaba.rocketmq.common.TopicConfig; +import com.alibaba.rocketmq.tools.admin.DefaultMQAdminExt; +import com.alibaba.rocketmq.tools.command.CommandUtil; +import com.alibaba.rocketmq.tools.command.SubCommand; + + +/** + * 修改、创建Topic配置命令 + * + * @author shijia.wxr + * @since 2013-7-21 + */ +public class UpdateTopicSubCommand implements SubCommand { + + @Override + public String commandName() { + return "updateTopic"; + } + + + @Override + public String commandDesc() { + return "Update or create topic"; + } + + + @Override + public Options buildCommandlineOptions(Options options) { + Option opt = new Option("b", "brokerAddr", true, "create topic to which broker"); + opt.setRequired(false); + options.addOption(opt); + + opt = new Option("c", "clusterName", true, "create topic to which cluster"); + opt.setRequired(false); + options.addOption(opt); + + opt = new Option("t", "topic", true, "topic name"); + opt.setRequired(true); + options.addOption(opt); + + opt = new Option("r", "readQueueNums", true, "set read queue nums"); + opt.setRequired(false); + options.addOption(opt); + + opt = new Option("w", "writeQueueNums", true, "set write queue nums"); + opt.setRequired(false); + options.addOption(opt); + + opt = new Option("p", "perm", true, "set topic's permission(W|R|WR)"); + opt.setRequired(false); + options.addOption(opt); + + return options; + } + + + @Override + public void execute(final CommandLine commandLine, final Options options) { + DefaultMQAdminExt defaultMQAdminExt = new DefaultMQAdminExt(); + + defaultMQAdminExt.setInstanceName(Long.toString(System.currentTimeMillis())); + + try { + TopicConfig topicConfig = new TopicConfig(); + topicConfig.setReadQueueNums(8); + topicConfig.setWriteQueueNums(8); + topicConfig.setTopicName(commandLine.getOptionValue('t').trim()); + + // readQueueNums + if (commandLine.hasOption('r')) { + topicConfig.setReadQueueNums(Integer.parseInt(commandLine.getOptionValue('r').trim())); + } + + // writeQueueNums + if (commandLine.hasOption('w')) { + topicConfig.setWriteQueueNums(Integer.parseInt(commandLine.getOptionValue('w').trim())); + } + + // perm + if (commandLine.hasOption('p')) { + topicConfig.setPerm(Integer.parseInt(commandLine.getOptionValue('p').trim())); + } + + if (commandLine.hasOption('b')) { + String addr = commandLine.getOptionValue('b').trim(); + + defaultMQAdminExt.start(); + defaultMQAdminExt.createAndUpdateTopicConfig(addr, topicConfig); + System.out.printf("create topic to %s success.\n", addr); + System.out.println(topicConfig); + return; + + } + else if (commandLine.hasOption('c')) { + String clusterName = commandLine.getOptionValue('c').trim(); + + defaultMQAdminExt.start(); + + Set masterSet = + CommandUtil.fetchMasterAddrByClusterName(defaultMQAdminExt, clusterName); + for (String addr : masterSet) { + defaultMQAdminExt.createAndUpdateTopicConfig(addr, topicConfig); + System.out.printf("create topic to %s success.\n", addr); + } + System.out.println(topicConfig); + return; + } + + MixAll.printCommandLineHelp("mqadmin " + this.commandName(), options); + } + catch (Exception e) { + e.printStackTrace(); + } + finally { + defaultMQAdminExt.shutdown(); + } + } +} diff --git a/test/consumer.sh b/test/consumer.sh new file mode 100644 index 00000000..fbeb1789 --- /dev/null +++ b/test/consumer.sh @@ -0,0 +1,6 @@ +#!/bin/sh + +# +# $Id: consumer.sh 1831 2013-05-16 01:39:51Z shijia.wxr $ +# +sh ./runclass.sh com.alibaba.rocketmq.example.operation.Consumer $@ diff --git a/test/master.sh b/test/master.sh deleted file mode 100644 index 2693a9d7..00000000 --- a/test/master.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/sh - -# -# $Id: master.sh 1054 2013-01-23 14:12:05Z shijia.wxr $ -# -sh ./runclass.sh com.taobao.metaq.research.storeha.BrokerMaster $@ diff --git a/test/mtclient.sh b/test/mtclient.sh deleted file mode 100644 index bb8b11b8..00000000 --- a/test/mtclient.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/sh - -# -# $Id: mtclient.sh 858 2012-12-24 06:33:27Z shijia.wxr $ -# -sh ./runclass.sh com.taobao.metaq.research.rpc.benchmark.MTClient $@ \ No newline at end of file diff --git a/test/producer.sh b/test/producer.sh new file mode 100644 index 00000000..058c6036 --- /dev/null +++ b/test/producer.sh @@ -0,0 +1,6 @@ +#!/bin/sh + +# +# $Id: producer.sh 1831 2013-05-16 01:39:51Z shijia.wxr $ +# +sh ./runclass.sh com.alibaba.rocketmq.example.operation.Producer $@ diff --git a/test/runclass.sh b/test/runclass.sh index 7a6f4c6b..5b638031 100644 --- a/test/runclass.sh +++ b/test/runclass.sh @@ -13,9 +13,9 @@ fi BASE_DIR=$(dirname $0)/.. CLASSPATH=.:${BASE_DIR}/conf:${CLASSPATH} -JAVA_OPT_1="-server -Xms4g -Xmx4g -Xmn1g -XX:PermSize=128m -XX:MaxPermSize=320m" +JAVA_OPT_1="-server -Xms1g -Xmx1g -Xmn256m -XX:PermSize=128m -XX:MaxPermSize=320m" JAVA_OPT_2="-XX:+UseConcMarkSweepGC -XX:+UseCMSCompactAtFullCollection -XX:CMSInitiatingOccupancyFraction=70 -XX:+CMSParallelRemarkEnabled -XX:SoftRefLRUPolicyMSPerMB=0 -XX:+CMSClassUnloadingEnabled -XX:SurvivorRatio=8 -XX:+DisableExplicitGC" -JAVA_OPT_3="-verbose:gc -Xloggc:${HOME}/metaq_gc.log -XX:+PrintGCDetails -XX:+PrintGCDateStamps" +JAVA_OPT_3="-verbose:gc -Xloggc:${HOME}/rocketmq_client_gc.log -XX:+PrintGCDetails -XX:+PrintGCDateStamps" JAVA_OPT_4="-XX:-OmitStackTraceInFastThrow" JAVA_OPT_5="-Djava.ext.dirs=${BASE_DIR}/lib" JAVA_OPT_6="-cp ${CLASSPATH}" diff --git a/test/server.sh b/test/server.sh deleted file mode 100644 index 16d70533..00000000 --- a/test/server.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/sh - -# -# $Id: server.sh 858 2012-12-24 06:33:27Z shijia.wxr $ -# -sh ./runclass.sh com.taobao.metaq.research.rpc.benchmark.Server $@ \ No newline at end of file diff --git a/test/slave.sh b/test/slave.sh deleted file mode 100644 index 452df610..00000000 --- a/test/slave.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/sh - -# -# $Id: slave.sh 1054 2013-01-23 14:12:05Z shijia.wxr $ -# -sh ./runclass.sh com.taobao.metaq.research.storeha.BrokerSlave $@ diff --git a/test/tools.sh b/test/tools.sh deleted file mode 100644 index b92bfcf9..00000000 --- a/test/tools.sh +++ /dev/null @@ -1,27 +0,0 @@ -#!/bin/sh - -# -# $Id: tools.sh 828 2012-12-21 08:30:52Z shijia.wxr $ -# - -if [ $# -lt 1 ]; -then - echo "USAGE: $0 classname opts" - exit 1 -fi - -BASE_DIR=$(dirname $0)/.. -CLASSPATH=.:${BASE_DIR}/conf:${CLASSPATH} - -JAVA_OPT_1="-Djava.ext.dirs=${BASE_DIR}/lib -cp ${CLASSPATH}" - - -if [ -z "$JAVA_HOME" ]; then - JAVA_HOME=/opt/taobao/java -fi - -JAVA="$JAVA_HOME/bin/java" - -JAVA_OPTS="${JAVA_OPT_1}" - -$JAVA $JAVA_OPTS $@ diff --git a/webroot/bootstrap/css/bootstrap-responsive.css b/webroot/bootstrap/css/bootstrap-responsive.css deleted file mode 100644 index fcd72f7a..00000000 --- a/webroot/bootstrap/css/bootstrap-responsive.css +++ /dev/null @@ -1,1109 +0,0 @@ -/*! - * Bootstrap Responsive v2.3.1 - * - * Copyright 2012 Twitter, Inc - * Licensed under the Apache License v2.0 - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Designed and built with all the love in the world @twitter by @mdo and @fat. - */ - -.clearfix { - *zoom: 1; -} - -.clearfix:before, -.clearfix:after { - display: table; - line-height: 0; - content: ""; -} - -.clearfix:after { - clear: both; -} - -.hide-text { - font: 0/0 a; - color: transparent; - text-shadow: none; - background-color: transparent; - border: 0; -} - -.input-block-level { - display: block; - width: 100%; - min-height: 30px; - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; -} - -@-ms-viewport { - width: device-width; -} - -.hidden { - display: none; - visibility: hidden; -} - -.visible-phone { - display: none !important; -} - -.visible-tablet { - display: none !important; -} - -.hidden-desktop { - display: none !important; -} - -.visible-desktop { - display: inherit !important; -} - -@media (min-width: 768px) and (max-width: 979px) { - .hidden-desktop { - display: inherit !important; - } - .visible-desktop { - display: none !important ; - } - .visible-tablet { - display: inherit !important; - } - .hidden-tablet { - display: none !important; - } -} - -@media (max-width: 767px) { - .hidden-desktop { - display: inherit !important; - } - .visible-desktop { - display: none !important; - } - .visible-phone { - display: inherit !important; - } - .hidden-phone { - display: none !important; - } -} - -.visible-print { - display: none !important; -} - -@media print { - .visible-print { - display: inherit !important; - } - .hidden-print { - display: none !important; - } -} - -@media (min-width: 1200px) { - .row { - margin-left: -30px; - *zoom: 1; - } - .row:before, - .row:after { - display: table; - line-height: 0; - content: ""; - } - .row:after { - clear: both; - } - [class*="span"] { - float: left; - min-height: 1px; - margin-left: 30px; - } - .container, - .navbar-static-top .container, - .navbar-fixed-top .container, - .navbar-fixed-bottom .container { - width: 1170px; - } - .span12 { - width: 1170px; - } - .span11 { - width: 1070px; - } - .span10 { - width: 970px; - } - .span9 { - width: 870px; - } - .span8 { - width: 770px; - } - .span7 { - width: 670px; - } - .span6 { - width: 570px; - } - .span5 { - width: 470px; - } - .span4 { - width: 370px; - } - .span3 { - width: 270px; - } - .span2 { - width: 170px; - } - .span1 { - width: 70px; - } - .offset12 { - margin-left: 1230px; - } - .offset11 { - margin-left: 1130px; - } - .offset10 { - margin-left: 1030px; - } - .offset9 { - margin-left: 930px; - } - .offset8 { - margin-left: 830px; - } - .offset7 { - margin-left: 730px; - } - .offset6 { - margin-left: 630px; - } - .offset5 { - margin-left: 530px; - } - .offset4 { - margin-left: 430px; - } - .offset3 { - margin-left: 330px; - } - .offset2 { - margin-left: 230px; - } - .offset1 { - margin-left: 130px; - } - .row-fluid { - width: 100%; - *zoom: 1; - } - .row-fluid:before, - .row-fluid:after { - display: table; - line-height: 0; - content: ""; - } - .row-fluid:after { - clear: both; - } - .row-fluid [class*="span"] { - display: block; - float: left; - width: 100%; - min-height: 30px; - margin-left: 2.564102564102564%; - *margin-left: 2.5109110747408616%; - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; - } - .row-fluid [class*="span"]:first-child { - margin-left: 0; - } - .row-fluid .controls-row [class*="span"] + [class*="span"] { - margin-left: 2.564102564102564%; - } - .row-fluid .span12 { - width: 100%; - *width: 99.94680851063829%; - } - .row-fluid .span11 { - width: 91.45299145299145%; - *width: 91.39979996362975%; - } - .row-fluid .span10 { - width: 82.90598290598291%; - *width: 82.8527914166212%; - } - .row-fluid .span9 { - width: 74.35897435897436%; - *width: 74.30578286961266%; - } - .row-fluid .span8 { - width: 65.81196581196582%; - *width: 65.75877432260411%; - } - .row-fluid .span7 { - width: 57.26495726495726%; - *width: 57.21176577559556%; - } - .row-fluid .span6 { - width: 48.717948717948715%; - *width: 48.664757228587014%; - } - .row-fluid .span5 { - width: 40.17094017094017%; - *width: 40.11774868157847%; - } - .row-fluid .span4 { - width: 31.623931623931625%; - *width: 31.570740134569924%; - } - .row-fluid .span3 { - width: 23.076923076923077%; - *width: 23.023731587561375%; - } - .row-fluid .span2 { - width: 14.52991452991453%; - *width: 14.476723040552828%; - } - .row-fluid .span1 { - width: 5.982905982905983%; - *width: 5.929714493544281%; - } - .row-fluid .offset12 { - margin-left: 105.12820512820512%; - *margin-left: 105.02182214948171%; - } - .row-fluid .offset12:first-child { - margin-left: 102.56410256410257%; - *margin-left: 102.45771958537915%; - } - .row-fluid .offset11 { - margin-left: 96.58119658119658%; - *margin-left: 96.47481360247316%; - } - .row-fluid .offset11:first-child { - margin-left: 94.01709401709402%; - *margin-left: 93.91071103837061%; - } - .row-fluid .offset10 { - margin-left: 88.03418803418803%; - *margin-left: 87.92780505546462%; - } - .row-fluid .offset10:first-child { - margin-left: 85.47008547008548%; - *margin-left: 85.36370249136206%; - } - .row-fluid .offset9 { - margin-left: 79.48717948717949%; - *margin-left: 79.38079650845607%; - } - .row-fluid .offset9:first-child { - margin-left: 76.92307692307693%; - *margin-left: 76.81669394435352%; - } - .row-fluid .offset8 { - margin-left: 70.94017094017094%; - *margin-left: 70.83378796144753%; - } - .row-fluid .offset8:first-child { - margin-left: 68.37606837606839%; - *margin-left: 68.26968539734497%; - } - .row-fluid .offset7 { - margin-left: 62.393162393162385%; - *margin-left: 62.28677941443899%; - } - .row-fluid .offset7:first-child { - margin-left: 59.82905982905982%; - *margin-left: 59.72267685033642%; - } - .row-fluid .offset6 { - margin-left: 53.84615384615384%; - *margin-left: 53.739770867430444%; - } - .row-fluid .offset6:first-child { - margin-left: 51.28205128205128%; - *margin-left: 51.175668303327875%; - } - .row-fluid .offset5 { - margin-left: 45.299145299145295%; - *margin-left: 45.1927623204219%; - } - .row-fluid .offset5:first-child { - margin-left: 42.73504273504273%; - *margin-left: 42.62865975631933%; - } - .row-fluid .offset4 { - margin-left: 36.75213675213675%; - *margin-left: 36.645753773413354%; - } - .row-fluid .offset4:first-child { - margin-left: 34.18803418803419%; - *margin-left: 34.081651209310785%; - } - .row-fluid .offset3 { - margin-left: 28.205128205128204%; - *margin-left: 28.0987452264048%; - } - .row-fluid .offset3:first-child { - margin-left: 25.641025641025642%; - *margin-left: 25.53464266230224%; - } - .row-fluid .offset2 { - margin-left: 19.65811965811966%; - *margin-left: 19.551736679396257%; - } - .row-fluid .offset2:first-child { - margin-left: 17.094017094017094%; - *margin-left: 16.98763411529369%; - } - .row-fluid .offset1 { - margin-left: 11.11111111111111%; - *margin-left: 11.004728132387708%; - } - .row-fluid .offset1:first-child { - margin-left: 8.547008547008547%; - *margin-left: 8.440625568285142%; - } - input, - textarea, - .uneditable-input { - margin-left: 0; - } - .controls-row [class*="span"] + [class*="span"] { - margin-left: 30px; - } - input.span12, - textarea.span12, - .uneditable-input.span12 { - width: 1156px; - } - input.span11, - textarea.span11, - .uneditable-input.span11 { - width: 1056px; - } - input.span10, - textarea.span10, - .uneditable-input.span10 { - width: 956px; - } - input.span9, - textarea.span9, - .uneditable-input.span9 { - width: 856px; - } - input.span8, - textarea.span8, - .uneditable-input.span8 { - width: 756px; - } - input.span7, - textarea.span7, - .uneditable-input.span7 { - width: 656px; - } - input.span6, - textarea.span6, - .uneditable-input.span6 { - width: 556px; - } - input.span5, - textarea.span5, - .uneditable-input.span5 { - width: 456px; - } - input.span4, - textarea.span4, - .uneditable-input.span4 { - width: 356px; - } - input.span3, - textarea.span3, - .uneditable-input.span3 { - width: 256px; - } - input.span2, - textarea.span2, - .uneditable-input.span2 { - width: 156px; - } - input.span1, - textarea.span1, - .uneditable-input.span1 { - width: 56px; - } - .thumbnails { - margin-left: -30px; - } - .thumbnails > li { - margin-left: 30px; - } - .row-fluid .thumbnails { - margin-left: 0; - } -} - -@media (min-width: 768px) and (max-width: 979px) { - .row { - margin-left: -20px; - *zoom: 1; - } - .row:before, - .row:after { - display: table; - line-height: 0; - content: ""; - } - .row:after { - clear: both; - } - [class*="span"] { - float: left; - min-height: 1px; - margin-left: 20px; - } - .container, - .navbar-static-top .container, - .navbar-fixed-top .container, - .navbar-fixed-bottom .container { - width: 724px; - } - .span12 { - width: 724px; - } - .span11 { - width: 662px; - } - .span10 { - width: 600px; - } - .span9 { - width: 538px; - } - .span8 { - width: 476px; - } - .span7 { - width: 414px; - } - .span6 { - width: 352px; - } - .span5 { - width: 290px; - } - .span4 { - width: 228px; - } - .span3 { - width: 166px; - } - .span2 { - width: 104px; - } - .span1 { - width: 42px; - } - .offset12 { - margin-left: 764px; - } - .offset11 { - margin-left: 702px; - } - .offset10 { - margin-left: 640px; - } - .offset9 { - margin-left: 578px; - } - .offset8 { - margin-left: 516px; - } - .offset7 { - margin-left: 454px; - } - .offset6 { - margin-left: 392px; - } - .offset5 { - margin-left: 330px; - } - .offset4 { - margin-left: 268px; - } - .offset3 { - margin-left: 206px; - } - .offset2 { - margin-left: 144px; - } - .offset1 { - margin-left: 82px; - } - .row-fluid { - width: 100%; - *zoom: 1; - } - .row-fluid:before, - .row-fluid:after { - display: table; - line-height: 0; - content: ""; - } - .row-fluid:after { - clear: both; - } - .row-fluid [class*="span"] { - display: block; - float: left; - width: 100%; - min-height: 30px; - margin-left: 2.7624309392265194%; - *margin-left: 2.709239449864817%; - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; - } - .row-fluid [class*="span"]:first-child { - margin-left: 0; - } - .row-fluid .controls-row [class*="span"] + [class*="span"] { - margin-left: 2.7624309392265194%; - } - .row-fluid .span12 { - width: 100%; - *width: 99.94680851063829%; - } - .row-fluid .span11 { - width: 91.43646408839778%; - *width: 91.38327259903608%; - } - .row-fluid .span10 { - width: 82.87292817679558%; - *width: 82.81973668743387%; - } - .row-fluid .span9 { - width: 74.30939226519337%; - *width: 74.25620077583166%; - } - .row-fluid .span8 { - width: 65.74585635359117%; - *width: 65.69266486422946%; - } - .row-fluid .span7 { - width: 57.18232044198895%; - *width: 57.12912895262725%; - } - .row-fluid .span6 { - width: 48.61878453038674%; - *width: 48.56559304102504%; - } - .row-fluid .span5 { - width: 40.05524861878453%; - *width: 40.00205712942283%; - } - .row-fluid .span4 { - width: 31.491712707182323%; - *width: 31.43852121782062%; - } - .row-fluid .span3 { - width: 22.92817679558011%; - *width: 22.87498530621841%; - } - .row-fluid .span2 { - width: 14.3646408839779%; - *width: 14.311449394616199%; - } - .row-fluid .span1 { - width: 5.801104972375691%; - *width: 5.747913483013988%; - } - .row-fluid .offset12 { - margin-left: 105.52486187845304%; - *margin-left: 105.41847889972962%; - } - .row-fluid .offset12:first-child { - margin-left: 102.76243093922652%; - *margin-left: 102.6560479605031%; - } - .row-fluid .offset11 { - margin-left: 96.96132596685082%; - *margin-left: 96.8549429881274%; - } - .row-fluid .offset11:first-child { - margin-left: 94.1988950276243%; - *margin-left: 94.09251204890089%; - } - .row-fluid .offset10 { - margin-left: 88.39779005524862%; - *margin-left: 88.2914070765252%; - } - .row-fluid .offset10:first-child { - margin-left: 85.6353591160221%; - *margin-left: 85.52897613729868%; - } - .row-fluid .offset9 { - margin-left: 79.8342541436464%; - *margin-left: 79.72787116492299%; - } - .row-fluid .offset9:first-child { - margin-left: 77.07182320441989%; - *margin-left: 76.96544022569647%; - } - .row-fluid .offset8 { - margin-left: 71.2707182320442%; - *margin-left: 71.16433525332079%; - } - .row-fluid .offset8:first-child { - margin-left: 68.50828729281768%; - *margin-left: 68.40190431409427%; - } - .row-fluid .offset7 { - margin-left: 62.70718232044199%; - *margin-left: 62.600799341718584%; - } - .row-fluid .offset7:first-child { - margin-left: 59.94475138121547%; - *margin-left: 59.838368402492065%; - } - .row-fluid .offset6 { - margin-left: 54.14364640883978%; - *margin-left: 54.037263430116376%; - } - .row-fluid .offset6:first-child { - margin-left: 51.38121546961326%; - *margin-left: 51.27483249088986%; - } - .row-fluid .offset5 { - margin-left: 45.58011049723757%; - *margin-left: 45.47372751851417%; - } - .row-fluid .offset5:first-child { - margin-left: 42.81767955801105%; - *margin-left: 42.71129657928765%; - } - .row-fluid .offset4 { - margin-left: 37.01657458563536%; - *margin-left: 36.91019160691196%; - } - .row-fluid .offset4:first-child { - margin-left: 34.25414364640884%; - *margin-left: 34.14776066768544%; - } - .row-fluid .offset3 { - margin-left: 28.45303867403315%; - *margin-left: 28.346655695309746%; - } - .row-fluid .offset3:first-child { - margin-left: 25.69060773480663%; - *margin-left: 25.584224756083227%; - } - .row-fluid .offset2 { - margin-left: 19.88950276243094%; - *margin-left: 19.783119783707537%; - } - .row-fluid .offset2:first-child { - margin-left: 17.12707182320442%; - *margin-left: 17.02068884448102%; - } - .row-fluid .offset1 { - margin-left: 11.32596685082873%; - *margin-left: 11.219583872105325%; - } - .row-fluid .offset1:first-child { - margin-left: 8.56353591160221%; - *margin-left: 8.457152932878806%; - } - input, - textarea, - .uneditable-input { - margin-left: 0; - } - .controls-row [class*="span"] + [class*="span"] { - margin-left: 20px; - } - input.span12, - textarea.span12, - .uneditable-input.span12 { - width: 710px; - } - input.span11, - textarea.span11, - .uneditable-input.span11 { - width: 648px; - } - input.span10, - textarea.span10, - .uneditable-input.span10 { - width: 586px; - } - input.span9, - textarea.span9, - .uneditable-input.span9 { - width: 524px; - } - input.span8, - textarea.span8, - .uneditable-input.span8 { - width: 462px; - } - input.span7, - textarea.span7, - .uneditable-input.span7 { - width: 400px; - } - input.span6, - textarea.span6, - .uneditable-input.span6 { - width: 338px; - } - input.span5, - textarea.span5, - .uneditable-input.span5 { - width: 276px; - } - input.span4, - textarea.span4, - .uneditable-input.span4 { - width: 214px; - } - input.span3, - textarea.span3, - .uneditable-input.span3 { - width: 152px; - } - input.span2, - textarea.span2, - .uneditable-input.span2 { - width: 90px; - } - input.span1, - textarea.span1, - .uneditable-input.span1 { - width: 28px; - } -} - -@media (max-width: 767px) { - body { - padding-right: 20px; - padding-left: 20px; - } - .navbar-fixed-top, - .navbar-fixed-bottom, - .navbar-static-top { - margin-right: -20px; - margin-left: -20px; - } - .container-fluid { - padding: 0; - } - .dl-horizontal dt { - float: none; - width: auto; - clear: none; - text-align: left; - } - .dl-horizontal dd { - margin-left: 0; - } - .container { - width: auto; - } - .row-fluid { - width: 100%; - } - .row, - .thumbnails { - margin-left: 0; - } - .thumbnails > li { - float: none; - margin-left: 0; - } - [class*="span"], - .uneditable-input[class*="span"], - .row-fluid [class*="span"] { - display: block; - float: none; - width: 100%; - margin-left: 0; - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; - } - .span12, - .row-fluid .span12 { - width: 100%; - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; - } - .row-fluid [class*="offset"]:first-child { - margin-left: 0; - } - .input-large, - .input-xlarge, - .input-xxlarge, - input[class*="span"], - select[class*="span"], - textarea[class*="span"], - .uneditable-input { - display: block; - width: 100%; - min-height: 30px; - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; - } - .input-prepend input, - .input-append input, - .input-prepend input[class*="span"], - .input-append input[class*="span"] { - display: inline-block; - width: auto; - } - .controls-row [class*="span"] + [class*="span"] { - margin-left: 0; - } - .modal { - position: fixed; - top: 20px; - right: 20px; - left: 20px; - width: auto; - margin: 0; - } - .modal.fade { - top: -100px; - } - .modal.fade.in { - top: 20px; - } -} - -@media (max-width: 480px) { - .nav-collapse { - -webkit-transform: translate3d(0, 0, 0); - } - .page-header h1 small { - display: block; - line-height: 20px; - } - input[type="checkbox"], - input[type="radio"] { - border: 1px solid #ccc; - } - .form-horizontal .control-label { - float: none; - width: auto; - padding-top: 0; - text-align: left; - } - .form-horizontal .controls { - margin-left: 0; - } - .form-horizontal .control-list { - padding-top: 0; - } - .form-horizontal .form-actions { - padding-right: 10px; - padding-left: 10px; - } - .media .pull-left, - .media .pull-right { - display: block; - float: none; - margin-bottom: 10px; - } - .media-object { - margin-right: 0; - margin-left: 0; - } - .modal { - top: 10px; - right: 10px; - left: 10px; - } - .modal-header .close { - padding: 10px; - margin: -10px; - } - .carousel-caption { - position: static; - } -} - -@media (max-width: 979px) { - body { - padding-top: 0; - } - .navbar-fixed-top, - .navbar-fixed-bottom { - position: static; - } - .navbar-fixed-top { - margin-bottom: 20px; - } - .navbar-fixed-bottom { - margin-top: 20px; - } - .navbar-fixed-top .navbar-inner, - .navbar-fixed-bottom .navbar-inner { - padding: 5px; - } - .navbar .container { - width: auto; - padding: 0; - } - .navbar .brand { - padding-right: 10px; - padding-left: 10px; - margin: 0 0 0 -5px; - } - .nav-collapse { - clear: both; - } - .nav-collapse .nav { - float: none; - margin: 0 0 10px; - } - .nav-collapse .nav > li { - float: none; - } - .nav-collapse .nav > li > a { - margin-bottom: 2px; - } - .nav-collapse .nav > .divider-vertical { - display: none; - } - .nav-collapse .nav .nav-header { - color: #777777; - text-shadow: none; - } - .nav-collapse .nav > li > a, - .nav-collapse .dropdown-menu a { - padding: 9px 15px; - font-weight: bold; - color: #777777; - -webkit-border-radius: 3px; - -moz-border-radius: 3px; - border-radius: 3px; - } - .nav-collapse .btn { - padding: 4px 10px 4px; - font-weight: normal; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; - } - .nav-collapse .dropdown-menu li + li a { - margin-bottom: 2px; - } - .nav-collapse .nav > li > a:hover, - .nav-collapse .nav > li > a:focus, - .nav-collapse .dropdown-menu a:hover, - .nav-collapse .dropdown-menu a:focus { - background-color: #f2f2f2; - } - .navbar-inverse .nav-collapse .nav > li > a, - .navbar-inverse .nav-collapse .dropdown-menu a { - color: #999999; - } - .navbar-inverse .nav-collapse .nav > li > a:hover, - .navbar-inverse .nav-collapse .nav > li > a:focus, - .navbar-inverse .nav-collapse .dropdown-menu a:hover, - .navbar-inverse .nav-collapse .dropdown-menu a:focus { - background-color: #111111; - } - .nav-collapse.in .btn-group { - padding: 0; - margin-top: 5px; - } - .nav-collapse .dropdown-menu { - position: static; - top: auto; - left: auto; - display: none; - float: none; - max-width: none; - padding: 0; - margin: 0 15px; - background-color: transparent; - border: none; - -webkit-border-radius: 0; - -moz-border-radius: 0; - border-radius: 0; - -webkit-box-shadow: none; - -moz-box-shadow: none; - box-shadow: none; - } - .nav-collapse .open > .dropdown-menu { - display: block; - } - .nav-collapse .dropdown-menu:before, - .nav-collapse .dropdown-menu:after { - display: none; - } - .nav-collapse .dropdown-menu .divider { - display: none; - } - .nav-collapse .nav > li > .dropdown-menu:before, - .nav-collapse .nav > li > .dropdown-menu:after { - display: none; - } - .nav-collapse .navbar-form, - .nav-collapse .navbar-search { - float: none; - padding: 10px 15px; - margin: 10px 0; - border-top: 1px solid #f2f2f2; - border-bottom: 1px solid #f2f2f2; - -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1); - -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1); - box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1); - } - .navbar-inverse .nav-collapse .navbar-form, - .navbar-inverse .nav-collapse .navbar-search { - border-top-color: #111111; - border-bottom-color: #111111; - } - .navbar .nav-collapse .nav.pull-right { - float: none; - margin-left: 0; - } - .nav-collapse, - .nav-collapse.collapse { - height: 0; - overflow: hidden; - } - .navbar .btn-navbar { - display: block; - } - .navbar-static .navbar-inner { - padding-right: 10px; - padding-left: 10px; - } -} - -@media (min-width: 980px) { - .nav-collapse.collapse { - height: auto !important; - overflow: visible !important; - } -} diff --git a/webroot/bootstrap/css/bootstrap-responsive.min.css b/webroot/bootstrap/css/bootstrap-responsive.min.css deleted file mode 100644 index d1b7f4b0..00000000 --- a/webroot/bootstrap/css/bootstrap-responsive.min.css +++ /dev/null @@ -1,9 +0,0 @@ -/*! - * Bootstrap Responsive v2.3.1 - * - * Copyright 2012 Twitter, Inc - * Licensed under the Apache License v2.0 - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Designed and built with all the love in the world @twitter by @mdo and @fat. - */.clearfix{*zoom:1}.clearfix:before,.clearfix:after{display:table;line-height:0;content:""}.clearfix:after{clear:both}.hide-text{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.input-block-level{display:block;width:100%;min-height:30px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}@-ms-viewport{width:device-width}.hidden{display:none;visibility:hidden}.visible-phone{display:none!important}.visible-tablet{display:none!important}.hidden-desktop{display:none!important}.visible-desktop{display:inherit!important}@media(min-width:768px) and (max-width:979px){.hidden-desktop{display:inherit!important}.visible-desktop{display:none!important}.visible-tablet{display:inherit!important}.hidden-tablet{display:none!important}}@media(max-width:767px){.hidden-desktop{display:inherit!important}.visible-desktop{display:none!important}.visible-phone{display:inherit!important}.hidden-phone{display:none!important}}.visible-print{display:none!important}@media print{.visible-print{display:inherit!important}.hidden-print{display:none!important}}@media(min-width:1200px){.row{margin-left:-30px;*zoom:1}.row:before,.row:after{display:table;line-height:0;content:""}.row:after{clear:both}[class*="span"]{float:left;min-height:1px;margin-left:30px}.container,.navbar-static-top .container,.navbar-fixed-top .container,.navbar-fixed-bottom .container{width:1170px}.span12{width:1170px}.span11{width:1070px}.span10{width:970px}.span9{width:870px}.span8{width:770px}.span7{width:670px}.span6{width:570px}.span5{width:470px}.span4{width:370px}.span3{width:270px}.span2{width:170px}.span1{width:70px}.offset12{margin-left:1230px}.offset11{margin-left:1130px}.offset10{margin-left:1030px}.offset9{margin-left:930px}.offset8{margin-left:830px}.offset7{margin-left:730px}.offset6{margin-left:630px}.offset5{margin-left:530px}.offset4{margin-left:430px}.offset3{margin-left:330px}.offset2{margin-left:230px}.offset1{margin-left:130px}.row-fluid{width:100%;*zoom:1}.row-fluid:before,.row-fluid:after{display:table;line-height:0;content:""}.row-fluid:after{clear:both}.row-fluid [class*="span"]{display:block;float:left;width:100%;min-height:30px;margin-left:2.564102564102564%;*margin-left:2.5109110747408616%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.row-fluid [class*="span"]:first-child{margin-left:0}.row-fluid .controls-row [class*="span"]+[class*="span"]{margin-left:2.564102564102564%}.row-fluid .span12{width:100%;*width:99.94680851063829%}.row-fluid .span11{width:91.45299145299145%;*width:91.39979996362975%}.row-fluid .span10{width:82.90598290598291%;*width:82.8527914166212%}.row-fluid .span9{width:74.35897435897436%;*width:74.30578286961266%}.row-fluid .span8{width:65.81196581196582%;*width:65.75877432260411%}.row-fluid .span7{width:57.26495726495726%;*width:57.21176577559556%}.row-fluid .span6{width:48.717948717948715%;*width:48.664757228587014%}.row-fluid .span5{width:40.17094017094017%;*width:40.11774868157847%}.row-fluid .span4{width:31.623931623931625%;*width:31.570740134569924%}.row-fluid .span3{width:23.076923076923077%;*width:23.023731587561375%}.row-fluid .span2{width:14.52991452991453%;*width:14.476723040552828%}.row-fluid .span1{width:5.982905982905983%;*width:5.929714493544281%}.row-fluid .offset12{margin-left:105.12820512820512%;*margin-left:105.02182214948171%}.row-fluid .offset12:first-child{margin-left:102.56410256410257%;*margin-left:102.45771958537915%}.row-fluid .offset11{margin-left:96.58119658119658%;*margin-left:96.47481360247316%}.row-fluid .offset11:first-child{margin-left:94.01709401709402%;*margin-left:93.91071103837061%}.row-fluid .offset10{margin-left:88.03418803418803%;*margin-left:87.92780505546462%}.row-fluid .offset10:first-child{margin-left:85.47008547008548%;*margin-left:85.36370249136206%}.row-fluid .offset9{margin-left:79.48717948717949%;*margin-left:79.38079650845607%}.row-fluid .offset9:first-child{margin-left:76.92307692307693%;*margin-left:76.81669394435352%}.row-fluid .offset8{margin-left:70.94017094017094%;*margin-left:70.83378796144753%}.row-fluid .offset8:first-child{margin-left:68.37606837606839%;*margin-left:68.26968539734497%}.row-fluid .offset7{margin-left:62.393162393162385%;*margin-left:62.28677941443899%}.row-fluid .offset7:first-child{margin-left:59.82905982905982%;*margin-left:59.72267685033642%}.row-fluid .offset6{margin-left:53.84615384615384%;*margin-left:53.739770867430444%}.row-fluid .offset6:first-child{margin-left:51.28205128205128%;*margin-left:51.175668303327875%}.row-fluid .offset5{margin-left:45.299145299145295%;*margin-left:45.1927623204219%}.row-fluid .offset5:first-child{margin-left:42.73504273504273%;*margin-left:42.62865975631933%}.row-fluid .offset4{margin-left:36.75213675213675%;*margin-left:36.645753773413354%}.row-fluid .offset4:first-child{margin-left:34.18803418803419%;*margin-left:34.081651209310785%}.row-fluid .offset3{margin-left:28.205128205128204%;*margin-left:28.0987452264048%}.row-fluid .offset3:first-child{margin-left:25.641025641025642%;*margin-left:25.53464266230224%}.row-fluid .offset2{margin-left:19.65811965811966%;*margin-left:19.551736679396257%}.row-fluid .offset2:first-child{margin-left:17.094017094017094%;*margin-left:16.98763411529369%}.row-fluid .offset1{margin-left:11.11111111111111%;*margin-left:11.004728132387708%}.row-fluid .offset1:first-child{margin-left:8.547008547008547%;*margin-left:8.440625568285142%}input,textarea,.uneditable-input{margin-left:0}.controls-row [class*="span"]+[class*="span"]{margin-left:30px}input.span12,textarea.span12,.uneditable-input.span12{width:1156px}input.span11,textarea.span11,.uneditable-input.span11{width:1056px}input.span10,textarea.span10,.uneditable-input.span10{width:956px}input.span9,textarea.span9,.uneditable-input.span9{width:856px}input.span8,textarea.span8,.uneditable-input.span8{width:756px}input.span7,textarea.span7,.uneditable-input.span7{width:656px}input.span6,textarea.span6,.uneditable-input.span6{width:556px}input.span5,textarea.span5,.uneditable-input.span5{width:456px}input.span4,textarea.span4,.uneditable-input.span4{width:356px}input.span3,textarea.span3,.uneditable-input.span3{width:256px}input.span2,textarea.span2,.uneditable-input.span2{width:156px}input.span1,textarea.span1,.uneditable-input.span1{width:56px}.thumbnails{margin-left:-30px}.thumbnails>li{margin-left:30px}.row-fluid .thumbnails{margin-left:0}}@media(min-width:768px) and (max-width:979px){.row{margin-left:-20px;*zoom:1}.row:before,.row:after{display:table;line-height:0;content:""}.row:after{clear:both}[class*="span"]{float:left;min-height:1px;margin-left:20px}.container,.navbar-static-top .container,.navbar-fixed-top .container,.navbar-fixed-bottom .container{width:724px}.span12{width:724px}.span11{width:662px}.span10{width:600px}.span9{width:538px}.span8{width:476px}.span7{width:414px}.span6{width:352px}.span5{width:290px}.span4{width:228px}.span3{width:166px}.span2{width:104px}.span1{width:42px}.offset12{margin-left:764px}.offset11{margin-left:702px}.offset10{margin-left:640px}.offset9{margin-left:578px}.offset8{margin-left:516px}.offset7{margin-left:454px}.offset6{margin-left:392px}.offset5{margin-left:330px}.offset4{margin-left:268px}.offset3{margin-left:206px}.offset2{margin-left:144px}.offset1{margin-left:82px}.row-fluid{width:100%;*zoom:1}.row-fluid:before,.row-fluid:after{display:table;line-height:0;content:""}.row-fluid:after{clear:both}.row-fluid [class*="span"]{display:block;float:left;width:100%;min-height:30px;margin-left:2.7624309392265194%;*margin-left:2.709239449864817%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.row-fluid [class*="span"]:first-child{margin-left:0}.row-fluid .controls-row [class*="span"]+[class*="span"]{margin-left:2.7624309392265194%}.row-fluid .span12{width:100%;*width:99.94680851063829%}.row-fluid .span11{width:91.43646408839778%;*width:91.38327259903608%}.row-fluid .span10{width:82.87292817679558%;*width:82.81973668743387%}.row-fluid .span9{width:74.30939226519337%;*width:74.25620077583166%}.row-fluid .span8{width:65.74585635359117%;*width:65.69266486422946%}.row-fluid .span7{width:57.18232044198895%;*width:57.12912895262725%}.row-fluid .span6{width:48.61878453038674%;*width:48.56559304102504%}.row-fluid .span5{width:40.05524861878453%;*width:40.00205712942283%}.row-fluid .span4{width:31.491712707182323%;*width:31.43852121782062%}.row-fluid .span3{width:22.92817679558011%;*width:22.87498530621841%}.row-fluid .span2{width:14.3646408839779%;*width:14.311449394616199%}.row-fluid .span1{width:5.801104972375691%;*width:5.747913483013988%}.row-fluid .offset12{margin-left:105.52486187845304%;*margin-left:105.41847889972962%}.row-fluid .offset12:first-child{margin-left:102.76243093922652%;*margin-left:102.6560479605031%}.row-fluid .offset11{margin-left:96.96132596685082%;*margin-left:96.8549429881274%}.row-fluid .offset11:first-child{margin-left:94.1988950276243%;*margin-left:94.09251204890089%}.row-fluid .offset10{margin-left:88.39779005524862%;*margin-left:88.2914070765252%}.row-fluid .offset10:first-child{margin-left:85.6353591160221%;*margin-left:85.52897613729868%}.row-fluid .offset9{margin-left:79.8342541436464%;*margin-left:79.72787116492299%}.row-fluid .offset9:first-child{margin-left:77.07182320441989%;*margin-left:76.96544022569647%}.row-fluid .offset8{margin-left:71.2707182320442%;*margin-left:71.16433525332079%}.row-fluid .offset8:first-child{margin-left:68.50828729281768%;*margin-left:68.40190431409427%}.row-fluid .offset7{margin-left:62.70718232044199%;*margin-left:62.600799341718584%}.row-fluid .offset7:first-child{margin-left:59.94475138121547%;*margin-left:59.838368402492065%}.row-fluid .offset6{margin-left:54.14364640883978%;*margin-left:54.037263430116376%}.row-fluid .offset6:first-child{margin-left:51.38121546961326%;*margin-left:51.27483249088986%}.row-fluid .offset5{margin-left:45.58011049723757%;*margin-left:45.47372751851417%}.row-fluid .offset5:first-child{margin-left:42.81767955801105%;*margin-left:42.71129657928765%}.row-fluid .offset4{margin-left:37.01657458563536%;*margin-left:36.91019160691196%}.row-fluid .offset4:first-child{margin-left:34.25414364640884%;*margin-left:34.14776066768544%}.row-fluid .offset3{margin-left:28.45303867403315%;*margin-left:28.346655695309746%}.row-fluid .offset3:first-child{margin-left:25.69060773480663%;*margin-left:25.584224756083227%}.row-fluid .offset2{margin-left:19.88950276243094%;*margin-left:19.783119783707537%}.row-fluid .offset2:first-child{margin-left:17.12707182320442%;*margin-left:17.02068884448102%}.row-fluid .offset1{margin-left:11.32596685082873%;*margin-left:11.219583872105325%}.row-fluid .offset1:first-child{margin-left:8.56353591160221%;*margin-left:8.457152932878806%}input,textarea,.uneditable-input{margin-left:0}.controls-row [class*="span"]+[class*="span"]{margin-left:20px}input.span12,textarea.span12,.uneditable-input.span12{width:710px}input.span11,textarea.span11,.uneditable-input.span11{width:648px}input.span10,textarea.span10,.uneditable-input.span10{width:586px}input.span9,textarea.span9,.uneditable-input.span9{width:524px}input.span8,textarea.span8,.uneditable-input.span8{width:462px}input.span7,textarea.span7,.uneditable-input.span7{width:400px}input.span6,textarea.span6,.uneditable-input.span6{width:338px}input.span5,textarea.span5,.uneditable-input.span5{width:276px}input.span4,textarea.span4,.uneditable-input.span4{width:214px}input.span3,textarea.span3,.uneditable-input.span3{width:152px}input.span2,textarea.span2,.uneditable-input.span2{width:90px}input.span1,textarea.span1,.uneditable-input.span1{width:28px}}@media(max-width:767px){body{padding-right:20px;padding-left:20px}.navbar-fixed-top,.navbar-fixed-bottom,.navbar-static-top{margin-right:-20px;margin-left:-20px}.container-fluid{padding:0}.dl-horizontal dt{float:none;width:auto;clear:none;text-align:left}.dl-horizontal dd{margin-left:0}.container{width:auto}.row-fluid{width:100%}.row,.thumbnails{margin-left:0}.thumbnails>li{float:none;margin-left:0}[class*="span"],.uneditable-input[class*="span"],.row-fluid [class*="span"]{display:block;float:none;width:100%;margin-left:0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.span12,.row-fluid .span12{width:100%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.row-fluid [class*="offset"]:first-child{margin-left:0}.input-large,.input-xlarge,.input-xxlarge,input[class*="span"],select[class*="span"],textarea[class*="span"],.uneditable-input{display:block;width:100%;min-height:30px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.input-prepend input,.input-append input,.input-prepend input[class*="span"],.input-append input[class*="span"]{display:inline-block;width:auto}.controls-row [class*="span"]+[class*="span"]{margin-left:0}.modal{position:fixed;top:20px;right:20px;left:20px;width:auto;margin:0}.modal.fade{top:-100px}.modal.fade.in{top:20px}}@media(max-width:480px){.nav-collapse{-webkit-transform:translate3d(0,0,0)}.page-header h1 small{display:block;line-height:20px}input[type="checkbox"],input[type="radio"]{border:1px solid #ccc}.form-horizontal .control-label{float:none;width:auto;padding-top:0;text-align:left}.form-horizontal .controls{margin-left:0}.form-horizontal .control-list{padding-top:0}.form-horizontal .form-actions{padding-right:10px;padding-left:10px}.media .pull-left,.media .pull-right{display:block;float:none;margin-bottom:10px}.media-object{margin-right:0;margin-left:0}.modal{top:10px;right:10px;left:10px}.modal-header .close{padding:10px;margin:-10px}.carousel-caption{position:static}}@media(max-width:979px){body{padding-top:0}.navbar-fixed-top,.navbar-fixed-bottom{position:static}.navbar-fixed-top{margin-bottom:20px}.navbar-fixed-bottom{margin-top:20px}.navbar-fixed-top .navbar-inner,.navbar-fixed-bottom .navbar-inner{padding:5px}.navbar .container{width:auto;padding:0}.navbar .brand{padding-right:10px;padding-left:10px;margin:0 0 0 -5px}.nav-collapse{clear:both}.nav-collapse .nav{float:none;margin:0 0 10px}.nav-collapse .nav>li{float:none}.nav-collapse .nav>li>a{margin-bottom:2px}.nav-collapse .nav>.divider-vertical{display:none}.nav-collapse .nav .nav-header{color:#777;text-shadow:none}.nav-collapse .nav>li>a,.nav-collapse .dropdown-menu a{padding:9px 15px;font-weight:bold;color:#777;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.nav-collapse .btn{padding:4px 10px 4px;font-weight:normal;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.nav-collapse .dropdown-menu li+li a{margin-bottom:2px}.nav-collapse .nav>li>a:hover,.nav-collapse .nav>li>a:focus,.nav-collapse .dropdown-menu a:hover,.nav-collapse .dropdown-menu a:focus{background-color:#f2f2f2}.navbar-inverse .nav-collapse .nav>li>a,.navbar-inverse .nav-collapse .dropdown-menu a{color:#999}.navbar-inverse .nav-collapse .nav>li>a:hover,.navbar-inverse .nav-collapse .nav>li>a:focus,.navbar-inverse .nav-collapse .dropdown-menu a:hover,.navbar-inverse .nav-collapse .dropdown-menu a:focus{background-color:#111}.nav-collapse.in .btn-group{padding:0;margin-top:5px}.nav-collapse .dropdown-menu{position:static;top:auto;left:auto;display:none;float:none;max-width:none;padding:0;margin:0 15px;background-color:transparent;border:0;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none}.nav-collapse .open>.dropdown-menu{display:block}.nav-collapse .dropdown-menu:before,.nav-collapse .dropdown-menu:after{display:none}.nav-collapse .dropdown-menu .divider{display:none}.nav-collapse .nav>li>.dropdown-menu:before,.nav-collapse .nav>li>.dropdown-menu:after{display:none}.nav-collapse .navbar-form,.nav-collapse .navbar-search{float:none;padding:10px 15px;margin:10px 0;border-top:1px solid #f2f2f2;border-bottom:1px solid #f2f2f2;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1);-moz-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1);box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1)}.navbar-inverse .nav-collapse .navbar-form,.navbar-inverse .nav-collapse .navbar-search{border-top-color:#111;border-bottom-color:#111}.navbar .nav-collapse .nav.pull-right{float:none;margin-left:0}.nav-collapse,.nav-collapse.collapse{height:0;overflow:hidden}.navbar .btn-navbar{display:block}.navbar-static .navbar-inner{padding-right:10px;padding-left:10px}}@media(min-width:980px){.nav-collapse.collapse{height:auto!important;overflow:visible!important}} diff --git a/webroot/bootstrap/css/bootstrap.css b/webroot/bootstrap/css/bootstrap.css deleted file mode 100644 index 2f56af33..00000000 --- a/webroot/bootstrap/css/bootstrap.css +++ /dev/null @@ -1,6158 +0,0 @@ -/*! - * Bootstrap v2.3.1 - * - * Copyright 2012 Twitter, Inc - * Licensed under the Apache License v2.0 - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Designed and built with all the love in the world @twitter by @mdo and @fat. - */ - -.clearfix { - *zoom: 1; -} - -.clearfix:before, -.clearfix:after { - display: table; - line-height: 0; - content: ""; -} - -.clearfix:after { - clear: both; -} - -.hide-text { - font: 0/0 a; - color: transparent; - text-shadow: none; - background-color: transparent; - border: 0; -} - -.input-block-level { - display: block; - width: 100%; - min-height: 30px; - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; -} - -article, -aside, -details, -figcaption, -figure, -footer, -header, -hgroup, -nav, -section { - display: block; -} - -audio, -canvas, -video { - display: inline-block; - *display: inline; - *zoom: 1; -} - -audio:not([controls]) { - display: none; -} - -html { - font-size: 100%; - -webkit-text-size-adjust: 100%; - -ms-text-size-adjust: 100%; -} - -a:focus { - outline: thin dotted #333; - outline: 5px auto -webkit-focus-ring-color; - outline-offset: -2px; -} - -a:hover, -a:active { - outline: 0; -} - -sub, -sup { - position: relative; - font-size: 75%; - line-height: 0; - vertical-align: baseline; -} - -sup { - top: -0.5em; -} - -sub { - bottom: -0.25em; -} - -img { - width: auto\9; - height: auto; - max-width: 100%; - vertical-align: middle; - border: 0; - -ms-interpolation-mode: bicubic; -} - -#map_canvas img, -.google-maps img { - max-width: none; -} - -button, -input, -select, -textarea { - margin: 0; - font-size: 100%; - vertical-align: middle; -} - -button, -input { - *overflow: visible; - line-height: normal; -} - -button::-moz-focus-inner, -input::-moz-focus-inner { - padding: 0; - border: 0; -} - -button, -html input[type="button"], -input[type="reset"], -input[type="submit"] { - cursor: pointer; - -webkit-appearance: button; -} - -label, -select, -button, -input[type="button"], -input[type="reset"], -input[type="submit"], -input[type="radio"], -input[type="checkbox"] { - cursor: pointer; -} - -input[type="search"] { - -webkit-box-sizing: content-box; - -moz-box-sizing: content-box; - box-sizing: content-box; - -webkit-appearance: textfield; -} - -input[type="search"]::-webkit-search-decoration, -input[type="search"]::-webkit-search-cancel-button { - -webkit-appearance: none; -} - -textarea { - overflow: auto; - vertical-align: top; -} - -@media print { - * { - color: #000 !important; - text-shadow: none !important; - background: transparent !important; - box-shadow: none !important; - } - a, - a:visited { - text-decoration: underline; - } - a[href]:after { - content: " (" attr(href) ")"; - } - abbr[title]:after { - content: " (" attr(title) ")"; - } - .ir a:after, - a[href^="javascript:"]:after, - a[href^="#"]:after { - content: ""; - } - pre, - blockquote { - border: 1px solid #999; - page-break-inside: avoid; - } - thead { - display: table-header-group; - } - tr, - img { - page-break-inside: avoid; - } - img { - max-width: 100% !important; - } - @page { - margin: 0.5cm; - } - p, - h2, - h3 { - orphans: 3; - widows: 3; - } - h2, - h3 { - page-break-after: avoid; - } -} - -body { - margin: 0; - font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; - font-size: 14px; - line-height: 20px; - color: #333333; - background-color: #ffffff; -} - -a { - color: #0088cc; - text-decoration: none; -} - -a:hover, -a:focus { - color: #005580; - text-decoration: underline; -} - -.img-rounded { - -webkit-border-radius: 6px; - -moz-border-radius: 6px; - border-radius: 6px; -} - -.img-polaroid { - padding: 4px; - background-color: #fff; - border: 1px solid #ccc; - border: 1px solid rgba(0, 0, 0, 0.2); - -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); - -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); - box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); -} - -.img-circle { - -webkit-border-radius: 500px; - -moz-border-radius: 500px; - border-radius: 500px; -} - -.row { - margin-left: -20px; - *zoom: 1; -} - -.row:before, -.row:after { - display: table; - line-height: 0; - content: ""; -} - -.row:after { - clear: both; -} - -[class*="span"] { - float: left; - min-height: 1px; - margin-left: 20px; -} - -.container, -.navbar-static-top .container, -.navbar-fixed-top .container, -.navbar-fixed-bottom .container { - width: 940px; -} - -.span12 { - width: 940px; -} - -.span11 { - width: 860px; -} - -.span10 { - width: 780px; -} - -.span9 { - width: 700px; -} - -.span8 { - width: 620px; -} - -.span7 { - width: 540px; -} - -.span6 { - width: 460px; -} - -.span5 { - width: 380px; -} - -.span4 { - width: 300px; -} - -.span3 { - width: 220px; -} - -.span2 { - width: 140px; -} - -.span1 { - width: 60px; -} - -.offset12 { - margin-left: 980px; -} - -.offset11 { - margin-left: 900px; -} - -.offset10 { - margin-left: 820px; -} - -.offset9 { - margin-left: 740px; -} - -.offset8 { - margin-left: 660px; -} - -.offset7 { - margin-left: 580px; -} - -.offset6 { - margin-left: 500px; -} - -.offset5 { - margin-left: 420px; -} - -.offset4 { - margin-left: 340px; -} - -.offset3 { - margin-left: 260px; -} - -.offset2 { - margin-left: 180px; -} - -.offset1 { - margin-left: 100px; -} - -.row-fluid { - width: 100%; - *zoom: 1; -} - -.row-fluid:before, -.row-fluid:after { - display: table; - line-height: 0; - content: ""; -} - -.row-fluid:after { - clear: both; -} - -.row-fluid [class*="span"] { - display: block; - float: left; - width: 100%; - min-height: 30px; - margin-left: 2.127659574468085%; - *margin-left: 2.074468085106383%; - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; -} - -.row-fluid [class*="span"]:first-child { - margin-left: 0; -} - -.row-fluid .controls-row [class*="span"] + [class*="span"] { - margin-left: 2.127659574468085%; -} - -.row-fluid .span12 { - width: 100%; - *width: 99.94680851063829%; -} - -.row-fluid .span11 { - width: 91.48936170212765%; - *width: 91.43617021276594%; -} - -.row-fluid .span10 { - width: 82.97872340425532%; - *width: 82.92553191489361%; -} - -.row-fluid .span9 { - width: 74.46808510638297%; - *width: 74.41489361702126%; -} - -.row-fluid .span8 { - width: 65.95744680851064%; - *width: 65.90425531914893%; -} - -.row-fluid .span7 { - width: 57.44680851063829%; - *width: 57.39361702127659%; -} - -.row-fluid .span6 { - width: 48.93617021276595%; - *width: 48.88297872340425%; -} - -.row-fluid .span5 { - width: 40.42553191489362%; - *width: 40.37234042553192%; -} - -.row-fluid .span4 { - width: 31.914893617021278%; - *width: 31.861702127659576%; -} - -.row-fluid .span3 { - width: 23.404255319148934%; - *width: 23.351063829787233%; -} - -.row-fluid .span2 { - width: 14.893617021276595%; - *width: 14.840425531914894%; -} - -.row-fluid .span1 { - width: 6.382978723404255%; - *width: 6.329787234042553%; -} - -.row-fluid .offset12 { - margin-left: 104.25531914893617%; - *margin-left: 104.14893617021275%; -} - -.row-fluid .offset12:first-child { - margin-left: 102.12765957446808%; - *margin-left: 102.02127659574467%; -} - -.row-fluid .offset11 { - margin-left: 95.74468085106382%; - *margin-left: 95.6382978723404%; -} - -.row-fluid .offset11:first-child { - margin-left: 93.61702127659574%; - *margin-left: 93.51063829787232%; -} - -.row-fluid .offset10 { - margin-left: 87.23404255319149%; - *margin-left: 87.12765957446807%; -} - -.row-fluid .offset10:first-child { - margin-left: 85.1063829787234%; - *margin-left: 84.99999999999999%; -} - -.row-fluid .offset9 { - margin-left: 78.72340425531914%; - *margin-left: 78.61702127659572%; -} - -.row-fluid .offset9:first-child { - margin-left: 76.59574468085106%; - *margin-left: 76.48936170212764%; -} - -.row-fluid .offset8 { - margin-left: 70.2127659574468%; - *margin-left: 70.10638297872339%; -} - -.row-fluid .offset8:first-child { - margin-left: 68.08510638297872%; - *margin-left: 67.9787234042553%; -} - -.row-fluid .offset7 { - margin-left: 61.70212765957446%; - *margin-left: 61.59574468085106%; -} - -.row-fluid .offset7:first-child { - margin-left: 59.574468085106375%; - *margin-left: 59.46808510638297%; -} - -.row-fluid .offset6 { - margin-left: 53.191489361702125%; - *margin-left: 53.085106382978715%; -} - -.row-fluid .offset6:first-child { - margin-left: 51.063829787234035%; - *margin-left: 50.95744680851063%; -} - -.row-fluid .offset5 { - margin-left: 44.68085106382979%; - *margin-left: 44.57446808510638%; -} - -.row-fluid .offset5:first-child { - margin-left: 42.5531914893617%; - *margin-left: 42.4468085106383%; -} - -.row-fluid .offset4 { - margin-left: 36.170212765957444%; - *margin-left: 36.06382978723405%; -} - -.row-fluid .offset4:first-child { - margin-left: 34.04255319148936%; - *margin-left: 33.93617021276596%; -} - -.row-fluid .offset3 { - margin-left: 27.659574468085104%; - *margin-left: 27.5531914893617%; -} - -.row-fluid .offset3:first-child { - margin-left: 25.53191489361702%; - *margin-left: 25.425531914893618%; -} - -.row-fluid .offset2 { - margin-left: 19.148936170212764%; - *margin-left: 19.04255319148936%; -} - -.row-fluid .offset2:first-child { - margin-left: 17.02127659574468%; - *margin-left: 16.914893617021278%; -} - -.row-fluid .offset1 { - margin-left: 10.638297872340425%; - *margin-left: 10.53191489361702%; -} - -.row-fluid .offset1:first-child { - margin-left: 8.51063829787234%; - *margin-left: 8.404255319148938%; -} - -[class*="span"].hide, -.row-fluid [class*="span"].hide { - display: none; -} - -[class*="span"].pull-right, -.row-fluid [class*="span"].pull-right { - float: right; -} - -.container { - margin-right: auto; - margin-left: auto; - *zoom: 1; -} - -.container:before, -.container:after { - display: table; - line-height: 0; - content: ""; -} - -.container:after { - clear: both; -} - -.container-fluid { - padding-right: 20px; - padding-left: 20px; - *zoom: 1; -} - -.container-fluid:before, -.container-fluid:after { - display: table; - line-height: 0; - content: ""; -} - -.container-fluid:after { - clear: both; -} - -p { - margin: 0 0 10px; -} - -.lead { - margin-bottom: 20px; - font-size: 21px; - font-weight: 200; - line-height: 30px; -} - -small { - font-size: 85%; -} - -strong { - font-weight: bold; -} - -em { - font-style: italic; -} - -cite { - font-style: normal; -} - -.muted { - color: #999999; -} - -a.muted:hover, -a.muted:focus { - color: #808080; -} - -.text-warning { - color: #c09853; -} - -a.text-warning:hover, -a.text-warning:focus { - color: #a47e3c; -} - -.text-error { - color: #b94a48; -} - -a.text-error:hover, -a.text-error:focus { - color: #953b39; -} - -.text-info { - color: #3a87ad; -} - -a.text-info:hover, -a.text-info:focus { - color: #2d6987; -} - -.text-success { - color: #468847; -} - -a.text-success:hover, -a.text-success:focus { - color: #356635; -} - -.text-left { - text-align: left; -} - -.text-right { - text-align: right; -} - -.text-center { - text-align: center; -} - -h1, -h2, -h3, -h4, -h5, -h6 { - margin: 10px 0; - font-family: inherit; - font-weight: bold; - line-height: 20px; - color: inherit; - text-rendering: optimizelegibility; -} - -h1 small, -h2 small, -h3 small, -h4 small, -h5 small, -h6 small { - font-weight: normal; - line-height: 1; - color: #999999; -} - -h1, -h2, -h3 { - line-height: 40px; -} - -h1 { - font-size: 38.5px; -} - -h2 { - font-size: 31.5px; -} - -h3 { - font-size: 24.5px; -} - -h4 { - font-size: 17.5px; -} - -h5 { - font-size: 14px; -} - -h6 { - font-size: 11.9px; -} - -h1 small { - font-size: 24.5px; -} - -h2 small { - font-size: 17.5px; -} - -h3 small { - font-size: 14px; -} - -h4 small { - font-size: 14px; -} - -.page-header { - padding-bottom: 9px; - margin: 20px 0 30px; - border-bottom: 1px solid #eeeeee; -} - -ul, -ol { - padding: 0; - margin: 0 0 10px 25px; -} - -ul ul, -ul ol, -ol ol, -ol ul { - margin-bottom: 0; -} - -li { - line-height: 20px; -} - -ul.unstyled, -ol.unstyled { - margin-left: 0; - list-style: none; -} - -ul.inline, -ol.inline { - margin-left: 0; - list-style: none; -} - -ul.inline > li, -ol.inline > li { - display: inline-block; - *display: inline; - padding-right: 5px; - padding-left: 5px; - *zoom: 1; -} - -dl { - margin-bottom: 20px; -} - -dt, -dd { - line-height: 20px; -} - -dt { - font-weight: bold; -} - -dd { - margin-left: 10px; -} - -.dl-horizontal { - *zoom: 1; -} - -.dl-horizontal:before, -.dl-horizontal:after { - display: table; - line-height: 0; - content: ""; -} - -.dl-horizontal:after { - clear: both; -} - -.dl-horizontal dt { - float: left; - width: 160px; - overflow: hidden; - clear: left; - text-align: right; - text-overflow: ellipsis; - white-space: nowrap; -} - -.dl-horizontal dd { - margin-left: 180px; -} - -hr { - margin: 20px 0; - border: 0; - border-top: 1px solid #eeeeee; - border-bottom: 1px solid #ffffff; -} - -abbr[title], -abbr[data-original-title] { - cursor: help; - border-bottom: 1px dotted #999999; -} - -abbr.initialism { - font-size: 90%; - text-transform: uppercase; -} - -blockquote { - padding: 0 0 0 15px; - margin: 0 0 20px; - border-left: 5px solid #eeeeee; -} - -blockquote p { - margin-bottom: 0; - font-size: 17.5px; - font-weight: 300; - line-height: 1.25; -} - -blockquote small { - display: block; - line-height: 20px; - color: #999999; -} - -blockquote small:before { - content: '\2014 \00A0'; -} - -blockquote.pull-right { - float: right; - padding-right: 15px; - padding-left: 0; - border-right: 5px solid #eeeeee; - border-left: 0; -} - -blockquote.pull-right p, -blockquote.pull-right small { - text-align: right; -} - -blockquote.pull-right small:before { - content: ''; -} - -blockquote.pull-right small:after { - content: '\00A0 \2014'; -} - -q:before, -q:after, -blockquote:before, -blockquote:after { - content: ""; -} - -address { - display: block; - margin-bottom: 20px; - font-style: normal; - line-height: 20px; -} - -code, -pre { - padding: 0 3px 2px; - font-family: Monaco, Menlo, Consolas, "Courier New", monospace; - font-size: 12px; - color: #333333; - -webkit-border-radius: 3px; - -moz-border-radius: 3px; - border-radius: 3px; -} - -code { - padding: 2px 4px; - color: #d14; - white-space: nowrap; - background-color: #f7f7f9; - border: 1px solid #e1e1e8; -} - -pre { - display: block; - padding: 9.5px; - margin: 0 0 10px; - font-size: 13px; - line-height: 20px; - word-break: break-all; - word-wrap: break-word; - white-space: pre; - white-space: pre-wrap; - background-color: #f5f5f5; - border: 1px solid #ccc; - border: 1px solid rgba(0, 0, 0, 0.15); - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; -} - -pre.prettyprint { - margin-bottom: 20px; -} - -pre code { - padding: 0; - color: inherit; - white-space: pre; - white-space: pre-wrap; - background-color: transparent; - border: 0; -} - -.pre-scrollable { - max-height: 340px; - overflow-y: scroll; -} - -form { - margin: 0 0 20px; -} - -fieldset { - padding: 0; - margin: 0; - border: 0; -} - -legend { - display: block; - width: 100%; - padding: 0; - margin-bottom: 20px; - font-size: 21px; - line-height: 40px; - color: #333333; - border: 0; - border-bottom: 1px solid #e5e5e5; -} - -legend small { - font-size: 15px; - color: #999999; -} - -label, -input, -button, -select, -textarea { - font-size: 14px; - font-weight: normal; - line-height: 20px; -} - -input, -button, -select, -textarea { - font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; -} - -label { - display: block; - margin-bottom: 5px; -} - -select, -textarea, -input[type="text"], -input[type="password"], -input[type="datetime"], -input[type="datetime-local"], -input[type="date"], -input[type="month"], -input[type="time"], -input[type="week"], -input[type="number"], -input[type="email"], -input[type="url"], -input[type="search"], -input[type="tel"], -input[type="color"], -.uneditable-input { - display: inline-block; - height: 20px; - padding: 4px 6px; - margin-bottom: 10px; - font-size: 14px; - line-height: 20px; - color: #555555; - vertical-align: middle; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; -} - -input, -textarea, -.uneditable-input { - width: 206px; -} - -textarea { - height: auto; -} - -textarea, -input[type="text"], -input[type="password"], -input[type="datetime"], -input[type="datetime-local"], -input[type="date"], -input[type="month"], -input[type="time"], -input[type="week"], -input[type="number"], -input[type="email"], -input[type="url"], -input[type="search"], -input[type="tel"], -input[type="color"], -.uneditable-input { - background-color: #ffffff; - border: 1px solid #cccccc; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); - -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); - box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); - -webkit-transition: border linear 0.2s, box-shadow linear 0.2s; - -moz-transition: border linear 0.2s, box-shadow linear 0.2s; - -o-transition: border linear 0.2s, box-shadow linear 0.2s; - transition: border linear 0.2s, box-shadow linear 0.2s; -} - -textarea:focus, -input[type="text"]:focus, -input[type="password"]:focus, -input[type="datetime"]:focus, -input[type="datetime-local"]:focus, -input[type="date"]:focus, -input[type="month"]:focus, -input[type="time"]:focus, -input[type="week"]:focus, -input[type="number"]:focus, -input[type="email"]:focus, -input[type="url"]:focus, -input[type="search"]:focus, -input[type="tel"]:focus, -input[type="color"]:focus, -.uneditable-input:focus { - border-color: rgba(82, 168, 236, 0.8); - outline: 0; - outline: thin dotted \9; - /* IE6-9 */ - - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6); - -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6); - box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6); -} - -input[type="radio"], -input[type="checkbox"] { - margin: 4px 0 0; - margin-top: 1px \9; - *margin-top: 0; - line-height: normal; -} - -input[type="file"], -input[type="image"], -input[type="submit"], -input[type="reset"], -input[type="button"], -input[type="radio"], -input[type="checkbox"] { - width: auto; -} - -select, -input[type="file"] { - height: 30px; - /* In IE7, the height of the select element cannot be changed by height, only font-size */ - - *margin-top: 4px; - /* For IE7, add top margin to align select with labels */ - - line-height: 30px; -} - -select { - width: 220px; - background-color: #ffffff; - border: 1px solid #cccccc; -} - -select[multiple], -select[size] { - height: auto; -} - -select:focus, -input[type="file"]:focus, -input[type="radio"]:focus, -input[type="checkbox"]:focus { - outline: thin dotted #333; - outline: 5px auto -webkit-focus-ring-color; - outline-offset: -2px; -} - -.uneditable-input, -.uneditable-textarea { - color: #999999; - cursor: not-allowed; - background-color: #fcfcfc; - border-color: #cccccc; - -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025); - -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025); - box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025); -} - -.uneditable-input { - overflow: hidden; - white-space: nowrap; -} - -.uneditable-textarea { - width: auto; - height: auto; -} - -input:-moz-placeholder, -textarea:-moz-placeholder { - color: #999999; -} - -input:-ms-input-placeholder, -textarea:-ms-input-placeholder { - color: #999999; -} - -input::-webkit-input-placeholder, -textarea::-webkit-input-placeholder { - color: #999999; -} - -.radio, -.checkbox { - min-height: 20px; - padding-left: 20px; -} - -.radio input[type="radio"], -.checkbox input[type="checkbox"] { - float: left; - margin-left: -20px; -} - -.controls > .radio:first-child, -.controls > .checkbox:first-child { - padding-top: 5px; -} - -.radio.inline, -.checkbox.inline { - display: inline-block; - padding-top: 5px; - margin-bottom: 0; - vertical-align: middle; -} - -.radio.inline + .radio.inline, -.checkbox.inline + .checkbox.inline { - margin-left: 10px; -} - -.input-mini { - width: 60px; -} - -.input-small { - width: 90px; -} - -.input-medium { - width: 150px; -} - -.input-large { - width: 210px; -} - -.input-xlarge { - width: 270px; -} - -.input-xxlarge { - width: 530px; -} - -input[class*="span"], -select[class*="span"], -textarea[class*="span"], -.uneditable-input[class*="span"], -.row-fluid input[class*="span"], -.row-fluid select[class*="span"], -.row-fluid textarea[class*="span"], -.row-fluid .uneditable-input[class*="span"] { - float: none; - margin-left: 0; -} - -.input-append input[class*="span"], -.input-append .uneditable-input[class*="span"], -.input-prepend input[class*="span"], -.input-prepend .uneditable-input[class*="span"], -.row-fluid input[class*="span"], -.row-fluid select[class*="span"], -.row-fluid textarea[class*="span"], -.row-fluid .uneditable-input[class*="span"], -.row-fluid .input-prepend [class*="span"], -.row-fluid .input-append [class*="span"] { - display: inline-block; -} - -input, -textarea, -.uneditable-input { - margin-left: 0; -} - -.controls-row [class*="span"] + [class*="span"] { - margin-left: 20px; -} - -input.span12, -textarea.span12, -.uneditable-input.span12 { - width: 926px; -} - -input.span11, -textarea.span11, -.uneditable-input.span11 { - width: 846px; -} - -input.span10, -textarea.span10, -.uneditable-input.span10 { - width: 766px; -} - -input.span9, -textarea.span9, -.uneditable-input.span9 { - width: 686px; -} - -input.span8, -textarea.span8, -.uneditable-input.span8 { - width: 606px; -} - -input.span7, -textarea.span7, -.uneditable-input.span7 { - width: 526px; -} - -input.span6, -textarea.span6, -.uneditable-input.span6 { - width: 446px; -} - -input.span5, -textarea.span5, -.uneditable-input.span5 { - width: 366px; -} - -input.span4, -textarea.span4, -.uneditable-input.span4 { - width: 286px; -} - -input.span3, -textarea.span3, -.uneditable-input.span3 { - width: 206px; -} - -input.span2, -textarea.span2, -.uneditable-input.span2 { - width: 126px; -} - -input.span1, -textarea.span1, -.uneditable-input.span1 { - width: 46px; -} - -.controls-row { - *zoom: 1; -} - -.controls-row:before, -.controls-row:after { - display: table; - line-height: 0; - content: ""; -} - -.controls-row:after { - clear: both; -} - -.controls-row [class*="span"], -.row-fluid .controls-row [class*="span"] { - float: left; -} - -.controls-row .checkbox[class*="span"], -.controls-row .radio[class*="span"] { - padding-top: 5px; -} - -input[disabled], -select[disabled], -textarea[disabled], -input[readonly], -select[readonly], -textarea[readonly] { - cursor: not-allowed; - background-color: #eeeeee; -} - -input[type="radio"][disabled], -input[type="checkbox"][disabled], -input[type="radio"][readonly], -input[type="checkbox"][readonly] { - background-color: transparent; -} - -.control-group.warning .control-label, -.control-group.warning .help-block, -.control-group.warning .help-inline { - color: #c09853; -} - -.control-group.warning .checkbox, -.control-group.warning .radio, -.control-group.warning input, -.control-group.warning select, -.control-group.warning textarea { - color: #c09853; -} - -.control-group.warning input, -.control-group.warning select, -.control-group.warning textarea { - border-color: #c09853; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); - -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); - box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); -} - -.control-group.warning input:focus, -.control-group.warning select:focus, -.control-group.warning textarea:focus { - border-color: #a47e3c; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e; - -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e; - box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e; -} - -.control-group.warning .input-prepend .add-on, -.control-group.warning .input-append .add-on { - color: #c09853; - background-color: #fcf8e3; - border-color: #c09853; -} - -.control-group.error .control-label, -.control-group.error .help-block, -.control-group.error .help-inline { - color: #b94a48; -} - -.control-group.error .checkbox, -.control-group.error .radio, -.control-group.error input, -.control-group.error select, -.control-group.error textarea { - color: #b94a48; -} - -.control-group.error input, -.control-group.error select, -.control-group.error textarea { - border-color: #b94a48; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); - -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); - box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); -} - -.control-group.error input:focus, -.control-group.error select:focus, -.control-group.error textarea:focus { - border-color: #953b39; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392; - -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392; - box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392; -} - -.control-group.error .input-prepend .add-on, -.control-group.error .input-append .add-on { - color: #b94a48; - background-color: #f2dede; - border-color: #b94a48; -} - -.control-group.success .control-label, -.control-group.success .help-block, -.control-group.success .help-inline { - color: #468847; -} - -.control-group.success .checkbox, -.control-group.success .radio, -.control-group.success input, -.control-group.success select, -.control-group.success textarea { - color: #468847; -} - -.control-group.success input, -.control-group.success select, -.control-group.success textarea { - border-color: #468847; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); - -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); - box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); -} - -.control-group.success input:focus, -.control-group.success select:focus, -.control-group.success textarea:focus { - border-color: #356635; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b; - -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b; - box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b; -} - -.control-group.success .input-prepend .add-on, -.control-group.success .input-append .add-on { - color: #468847; - background-color: #dff0d8; - border-color: #468847; -} - -.control-group.info .control-label, -.control-group.info .help-block, -.control-group.info .help-inline { - color: #3a87ad; -} - -.control-group.info .checkbox, -.control-group.info .radio, -.control-group.info input, -.control-group.info select, -.control-group.info textarea { - color: #3a87ad; -} - -.control-group.info input, -.control-group.info select, -.control-group.info textarea { - border-color: #3a87ad; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); - -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); - box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); -} - -.control-group.info input:focus, -.control-group.info select:focus, -.control-group.info textarea:focus { - border-color: #2d6987; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3; - -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3; - box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3; -} - -.control-group.info .input-prepend .add-on, -.control-group.info .input-append .add-on { - color: #3a87ad; - background-color: #d9edf7; - border-color: #3a87ad; -} - -input:focus:invalid, -textarea:focus:invalid, -select:focus:invalid { - color: #b94a48; - border-color: #ee5f5b; -} - -input:focus:invalid:focus, -textarea:focus:invalid:focus, -select:focus:invalid:focus { - border-color: #e9322d; - -webkit-box-shadow: 0 0 6px #f8b9b7; - -moz-box-shadow: 0 0 6px #f8b9b7; - box-shadow: 0 0 6px #f8b9b7; -} - -.form-actions { - padding: 19px 20px 20px; - margin-top: 20px; - margin-bottom: 20px; - background-color: #f5f5f5; - border-top: 1px solid #e5e5e5; - *zoom: 1; -} - -.form-actions:before, -.form-actions:after { - display: table; - line-height: 0; - content: ""; -} - -.form-actions:after { - clear: both; -} - -.help-block, -.help-inline { - color: #595959; -} - -.help-block { - display: block; - margin-bottom: 10px; -} - -.help-inline { - display: inline-block; - *display: inline; - padding-left: 5px; - vertical-align: middle; - *zoom: 1; -} - -.input-append, -.input-prepend { - display: inline-block; - margin-bottom: 10px; - font-size: 0; - white-space: nowrap; - vertical-align: middle; -} - -.input-append input, -.input-prepend input, -.input-append select, -.input-prepend select, -.input-append .uneditable-input, -.input-prepend .uneditable-input, -.input-append .dropdown-menu, -.input-prepend .dropdown-menu, -.input-append .popover, -.input-prepend .popover { - font-size: 14px; -} - -.input-append input, -.input-prepend input, -.input-append select, -.input-prepend select, -.input-append .uneditable-input, -.input-prepend .uneditable-input { - position: relative; - margin-bottom: 0; - *margin-left: 0; - vertical-align: top; - -webkit-border-radius: 0 4px 4px 0; - -moz-border-radius: 0 4px 4px 0; - border-radius: 0 4px 4px 0; -} - -.input-append input:focus, -.input-prepend input:focus, -.input-append select:focus, -.input-prepend select:focus, -.input-append .uneditable-input:focus, -.input-prepend .uneditable-input:focus { - z-index: 2; -} - -.input-append .add-on, -.input-prepend .add-on { - display: inline-block; - width: auto; - height: 20px; - min-width: 16px; - padding: 4px 5px; - font-size: 14px; - font-weight: normal; - line-height: 20px; - text-align: center; - text-shadow: 0 1px 0 #ffffff; - background-color: #eeeeee; - border: 1px solid #ccc; -} - -.input-append .add-on, -.input-prepend .add-on, -.input-append .btn, -.input-prepend .btn, -.input-append .btn-group > .dropdown-toggle, -.input-prepend .btn-group > .dropdown-toggle { - vertical-align: top; - -webkit-border-radius: 0; - -moz-border-radius: 0; - border-radius: 0; -} - -.input-append .active, -.input-prepend .active { - background-color: #a9dba9; - border-color: #46a546; -} - -.input-prepend .add-on, -.input-prepend .btn { - margin-right: -1px; -} - -.input-prepend .add-on:first-child, -.input-prepend .btn:first-child { - -webkit-border-radius: 4px 0 0 4px; - -moz-border-radius: 4px 0 0 4px; - border-radius: 4px 0 0 4px; -} - -.input-append input, -.input-append select, -.input-append .uneditable-input { - -webkit-border-radius: 4px 0 0 4px; - -moz-border-radius: 4px 0 0 4px; - border-radius: 4px 0 0 4px; -} - -.input-append input + .btn-group .btn:last-child, -.input-append select + .btn-group .btn:last-child, -.input-append .uneditable-input + .btn-group .btn:last-child { - -webkit-border-radius: 0 4px 4px 0; - -moz-border-radius: 0 4px 4px 0; - border-radius: 0 4px 4px 0; -} - -.input-append .add-on, -.input-append .btn, -.input-append .btn-group { - margin-left: -1px; -} - -.input-append .add-on:last-child, -.input-append .btn:last-child, -.input-append .btn-group:last-child > .dropdown-toggle { - -webkit-border-radius: 0 4px 4px 0; - -moz-border-radius: 0 4px 4px 0; - border-radius: 0 4px 4px 0; -} - -.input-prepend.input-append input, -.input-prepend.input-append select, -.input-prepend.input-append .uneditable-input { - -webkit-border-radius: 0; - -moz-border-radius: 0; - border-radius: 0; -} - -.input-prepend.input-append input + .btn-group .btn, -.input-prepend.input-append select + .btn-group .btn, -.input-prepend.input-append .uneditable-input + .btn-group .btn { - -webkit-border-radius: 0 4px 4px 0; - -moz-border-radius: 0 4px 4px 0; - border-radius: 0 4px 4px 0; -} - -.input-prepend.input-append .add-on:first-child, -.input-prepend.input-append .btn:first-child { - margin-right: -1px; - -webkit-border-radius: 4px 0 0 4px; - -moz-border-radius: 4px 0 0 4px; - border-radius: 4px 0 0 4px; -} - -.input-prepend.input-append .add-on:last-child, -.input-prepend.input-append .btn:last-child { - margin-left: -1px; - -webkit-border-radius: 0 4px 4px 0; - -moz-border-radius: 0 4px 4px 0; - border-radius: 0 4px 4px 0; -} - -.input-prepend.input-append .btn-group:first-child { - margin-left: 0; -} - -input.search-query { - padding-right: 14px; - padding-right: 4px \9; - padding-left: 14px; - padding-left: 4px \9; - /* IE7-8 doesn't have border-radius, so don't indent the padding */ - - margin-bottom: 0; - -webkit-border-radius: 15px; - -moz-border-radius: 15px; - border-radius: 15px; -} - -/* Allow for input prepend/append in search forms */ - -.form-search .input-append .search-query, -.form-search .input-prepend .search-query { - -webkit-border-radius: 0; - -moz-border-radius: 0; - border-radius: 0; -} - -.form-search .input-append .search-query { - -webkit-border-radius: 14px 0 0 14px; - -moz-border-radius: 14px 0 0 14px; - border-radius: 14px 0 0 14px; -} - -.form-search .input-append .btn { - -webkit-border-radius: 0 14px 14px 0; - -moz-border-radius: 0 14px 14px 0; - border-radius: 0 14px 14px 0; -} - -.form-search .input-prepend .search-query { - -webkit-border-radius: 0 14px 14px 0; - -moz-border-radius: 0 14px 14px 0; - border-radius: 0 14px 14px 0; -} - -.form-search .input-prepend .btn { - -webkit-border-radius: 14px 0 0 14px; - -moz-border-radius: 14px 0 0 14px; - border-radius: 14px 0 0 14px; -} - -.form-search input, -.form-inline input, -.form-horizontal input, -.form-search textarea, -.form-inline textarea, -.form-horizontal textarea, -.form-search select, -.form-inline select, -.form-horizontal select, -.form-search .help-inline, -.form-inline .help-inline, -.form-horizontal .help-inline, -.form-search .uneditable-input, -.form-inline .uneditable-input, -.form-horizontal .uneditable-input, -.form-search .input-prepend, -.form-inline .input-prepend, -.form-horizontal .input-prepend, -.form-search .input-append, -.form-inline .input-append, -.form-horizontal .input-append { - display: inline-block; - *display: inline; - margin-bottom: 0; - vertical-align: middle; - *zoom: 1; -} - -.form-search .hide, -.form-inline .hide, -.form-horizontal .hide { - display: none; -} - -.form-search label, -.form-inline label, -.form-search .btn-group, -.form-inline .btn-group { - display: inline-block; -} - -.form-search .input-append, -.form-inline .input-append, -.form-search .input-prepend, -.form-inline .input-prepend { - margin-bottom: 0; -} - -.form-search .radio, -.form-search .checkbox, -.form-inline .radio, -.form-inline .checkbox { - padding-left: 0; - margin-bottom: 0; - vertical-align: middle; -} - -.form-search .radio input[type="radio"], -.form-search .checkbox input[type="checkbox"], -.form-inline .radio input[type="radio"], -.form-inline .checkbox input[type="checkbox"] { - float: left; - margin-right: 3px; - margin-left: 0; -} - -.control-group { - margin-bottom: 10px; -} - -legend + .control-group { - margin-top: 20px; - -webkit-margin-top-collapse: separate; -} - -.form-horizontal .control-group { - margin-bottom: 20px; - *zoom: 1; -} - -.form-horizontal .control-group:before, -.form-horizontal .control-group:after { - display: table; - line-height: 0; - content: ""; -} - -.form-horizontal .control-group:after { - clear: both; -} - -.form-horizontal .control-label { - float: left; - width: 160px; - padding-top: 5px; - text-align: right; -} - -.form-horizontal .controls { - *display: inline-block; - *padding-left: 20px; - margin-left: 180px; - *margin-left: 0; -} - -.form-horizontal .controls:first-child { - *padding-left: 180px; -} - -.form-horizontal .help-block { - margin-bottom: 0; -} - -.form-horizontal input + .help-block, -.form-horizontal select + .help-block, -.form-horizontal textarea + .help-block, -.form-horizontal .uneditable-input + .help-block, -.form-horizontal .input-prepend + .help-block, -.form-horizontal .input-append + .help-block { - margin-top: 10px; -} - -.form-horizontal .form-actions { - padding-left: 180px; -} - -table { - max-width: 100%; - background-color: transparent; - border-collapse: collapse; - border-spacing: 0; -} - -.table { - width: 100%; - margin-bottom: 20px; -} - -.table th, -.table td { - padding: 8px; - line-height: 20px; - text-align: left; - vertical-align: top; - border-top: 1px solid #dddddd; -} - -.table th { - font-weight: bold; -} - -.table thead th { - vertical-align: bottom; -} - -.table caption + thead tr:first-child th, -.table caption + thead tr:first-child td, -.table colgroup + thead tr:first-child th, -.table colgroup + thead tr:first-child td, -.table thead:first-child tr:first-child th, -.table thead:first-child tr:first-child td { - border-top: 0; -} - -.table tbody + tbody { - border-top: 2px solid #dddddd; -} - -.table .table { - background-color: #ffffff; -} - -.table-condensed th, -.table-condensed td { - padding: 4px 5px; -} - -.table-bordered { - border: 1px solid #dddddd; - border-collapse: separate; - *border-collapse: collapse; - border-left: 0; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; -} - -.table-bordered th, -.table-bordered td { - border-left: 1px solid #dddddd; -} - -.table-bordered caption + thead tr:first-child th, -.table-bordered caption + tbody tr:first-child th, -.table-bordered caption + tbody tr:first-child td, -.table-bordered colgroup + thead tr:first-child th, -.table-bordered colgroup + tbody tr:first-child th, -.table-bordered colgroup + tbody tr:first-child td, -.table-bordered thead:first-child tr:first-child th, -.table-bordered tbody:first-child tr:first-child th, -.table-bordered tbody:first-child tr:first-child td { - border-top: 0; -} - -.table-bordered thead:first-child tr:first-child > th:first-child, -.table-bordered tbody:first-child tr:first-child > td:first-child, -.table-bordered tbody:first-child tr:first-child > th:first-child { - -webkit-border-top-left-radius: 4px; - border-top-left-radius: 4px; - -moz-border-radius-topleft: 4px; -} - -.table-bordered thead:first-child tr:first-child > th:last-child, -.table-bordered tbody:first-child tr:first-child > td:last-child, -.table-bordered tbody:first-child tr:first-child > th:last-child { - -webkit-border-top-right-radius: 4px; - border-top-right-radius: 4px; - -moz-border-radius-topright: 4px; -} - -.table-bordered thead:last-child tr:last-child > th:first-child, -.table-bordered tbody:last-child tr:last-child > td:first-child, -.table-bordered tbody:last-child tr:last-child > th:first-child, -.table-bordered tfoot:last-child tr:last-child > td:first-child, -.table-bordered tfoot:last-child tr:last-child > th:first-child { - -webkit-border-bottom-left-radius: 4px; - border-bottom-left-radius: 4px; - -moz-border-radius-bottomleft: 4px; -} - -.table-bordered thead:last-child tr:last-child > th:last-child, -.table-bordered tbody:last-child tr:last-child > td:last-child, -.table-bordered tbody:last-child tr:last-child > th:last-child, -.table-bordered tfoot:last-child tr:last-child > td:last-child, -.table-bordered tfoot:last-child tr:last-child > th:last-child { - -webkit-border-bottom-right-radius: 4px; - border-bottom-right-radius: 4px; - -moz-border-radius-bottomright: 4px; -} - -.table-bordered tfoot + tbody:last-child tr:last-child td:first-child { - -webkit-border-bottom-left-radius: 0; - border-bottom-left-radius: 0; - -moz-border-radius-bottomleft: 0; -} - -.table-bordered tfoot + tbody:last-child tr:last-child td:last-child { - -webkit-border-bottom-right-radius: 0; - border-bottom-right-radius: 0; - -moz-border-radius-bottomright: 0; -} - -.table-bordered caption + thead tr:first-child th:first-child, -.table-bordered caption + tbody tr:first-child td:first-child, -.table-bordered colgroup + thead tr:first-child th:first-child, -.table-bordered colgroup + tbody tr:first-child td:first-child { - -webkit-border-top-left-radius: 4px; - border-top-left-radius: 4px; - -moz-border-radius-topleft: 4px; -} - -.table-bordered caption + thead tr:first-child th:last-child, -.table-bordered caption + tbody tr:first-child td:last-child, -.table-bordered colgroup + thead tr:first-child th:last-child, -.table-bordered colgroup + tbody tr:first-child td:last-child { - -webkit-border-top-right-radius: 4px; - border-top-right-radius: 4px; - -moz-border-radius-topright: 4px; -} - -.table-striped tbody > tr:nth-child(odd) > td, -.table-striped tbody > tr:nth-child(odd) > th { - background-color: #f9f9f9; -} - -.table-hover tbody tr:hover > td, -.table-hover tbody tr:hover > th { - background-color: #f5f5f5; -} - -table td[class*="span"], -table th[class*="span"], -.row-fluid table td[class*="span"], -.row-fluid table th[class*="span"] { - display: table-cell; - float: none; - margin-left: 0; -} - -.table td.span1, -.table th.span1 { - float: none; - width: 44px; - margin-left: 0; -} - -.table td.span2, -.table th.span2 { - float: none; - width: 124px; - margin-left: 0; -} - -.table td.span3, -.table th.span3 { - float: none; - width: 204px; - margin-left: 0; -} - -.table td.span4, -.table th.span4 { - float: none; - width: 284px; - margin-left: 0; -} - -.table td.span5, -.table th.span5 { - float: none; - width: 364px; - margin-left: 0; -} - -.table td.span6, -.table th.span6 { - float: none; - width: 444px; - margin-left: 0; -} - -.table td.span7, -.table th.span7 { - float: none; - width: 524px; - margin-left: 0; -} - -.table td.span8, -.table th.span8 { - float: none; - width: 604px; - margin-left: 0; -} - -.table td.span9, -.table th.span9 { - float: none; - width: 684px; - margin-left: 0; -} - -.table td.span10, -.table th.span10 { - float: none; - width: 764px; - margin-left: 0; -} - -.table td.span11, -.table th.span11 { - float: none; - width: 844px; - margin-left: 0; -} - -.table td.span12, -.table th.span12 { - float: none; - width: 924px; - margin-left: 0; -} - -.table tbody tr.success > td { - background-color: #dff0d8; -} - -.table tbody tr.error > td { - background-color: #f2dede; -} - -.table tbody tr.warning > td { - background-color: #fcf8e3; -} - -.table tbody tr.info > td { - background-color: #d9edf7; -} - -.table-hover tbody tr.success:hover > td { - background-color: #d0e9c6; -} - -.table-hover tbody tr.error:hover > td { - background-color: #ebcccc; -} - -.table-hover tbody tr.warning:hover > td { - background-color: #faf2cc; -} - -.table-hover tbody tr.info:hover > td { - background-color: #c4e3f3; -} - -[class^="icon-"], -[class*=" icon-"] { - display: inline-block; - width: 14px; - height: 14px; - margin-top: 1px; - *margin-right: .3em; - line-height: 14px; - vertical-align: text-top; - background-image: url("../img/glyphicons-halflings.png"); - background-position: 14px 14px; - background-repeat: no-repeat; -} - -/* White icons with optional class, or on hover/focus/active states of certain elements */ - -.icon-white, -.nav-pills > .active > a > [class^="icon-"], -.nav-pills > .active > a > [class*=" icon-"], -.nav-list > .active > a > [class^="icon-"], -.nav-list > .active > a > [class*=" icon-"], -.navbar-inverse .nav > .active > a > [class^="icon-"], -.navbar-inverse .nav > .active > a > [class*=" icon-"], -.dropdown-menu > li > a:hover > [class^="icon-"], -.dropdown-menu > li > a:focus > [class^="icon-"], -.dropdown-menu > li > a:hover > [class*=" icon-"], -.dropdown-menu > li > a:focus > [class*=" icon-"], -.dropdown-menu > .active > a > [class^="icon-"], -.dropdown-menu > .active > a > [class*=" icon-"], -.dropdown-submenu:hover > a > [class^="icon-"], -.dropdown-submenu:focus > a > [class^="icon-"], -.dropdown-submenu:hover > a > [class*=" icon-"], -.dropdown-submenu:focus > a > [class*=" icon-"] { - background-image: url("../img/glyphicons-halflings-white.png"); -} - -.icon-glass { - background-position: 0 0; -} - -.icon-music { - background-position: -24px 0; -} - -.icon-search { - background-position: -48px 0; -} - -.icon-envelope { - background-position: -72px 0; -} - -.icon-heart { - background-position: -96px 0; -} - -.icon-star { - background-position: -120px 0; -} - -.icon-star-empty { - background-position: -144px 0; -} - -.icon-user { - background-position: -168px 0; -} - -.icon-film { - background-position: -192px 0; -} - -.icon-th-large { - background-position: -216px 0; -} - -.icon-th { - background-position: -240px 0; -} - -.icon-th-list { - background-position: -264px 0; -} - -.icon-ok { - background-position: -288px 0; -} - -.icon-remove { - background-position: -312px 0; -} - -.icon-zoom-in { - background-position: -336px 0; -} - -.icon-zoom-out { - background-position: -360px 0; -} - -.icon-off { - background-position: -384px 0; -} - -.icon-signal { - background-position: -408px 0; -} - -.icon-cog { - background-position: -432px 0; -} - -.icon-trash { - background-position: -456px 0; -} - -.icon-home { - background-position: 0 -24px; -} - -.icon-file { - background-position: -24px -24px; -} - -.icon-time { - background-position: -48px -24px; -} - -.icon-road { - background-position: -72px -24px; -} - -.icon-download-alt { - background-position: -96px -24px; -} - -.icon-download { - background-position: -120px -24px; -} - -.icon-upload { - background-position: -144px -24px; -} - -.icon-inbox { - background-position: -168px -24px; -} - -.icon-play-circle { - background-position: -192px -24px; -} - -.icon-repeat { - background-position: -216px -24px; -} - -.icon-refresh { - background-position: -240px -24px; -} - -.icon-list-alt { - background-position: -264px -24px; -} - -.icon-lock { - background-position: -287px -24px; -} - -.icon-flag { - background-position: -312px -24px; -} - -.icon-headphones { - background-position: -336px -24px; -} - -.icon-volume-off { - background-position: -360px -24px; -} - -.icon-volume-down { - background-position: -384px -24px; -} - -.icon-volume-up { - background-position: -408px -24px; -} - -.icon-qrcode { - background-position: -432px -24px; -} - -.icon-barcode { - background-position: -456px -24px; -} - -.icon-tag { - background-position: 0 -48px; -} - -.icon-tags { - background-position: -25px -48px; -} - -.icon-book { - background-position: -48px -48px; -} - -.icon-bookmark { - background-position: -72px -48px; -} - -.icon-print { - background-position: -96px -48px; -} - -.icon-camera { - background-position: -120px -48px; -} - -.icon-font { - background-position: -144px -48px; -} - -.icon-bold { - background-position: -167px -48px; -} - -.icon-italic { - background-position: -192px -48px; -} - -.icon-text-height { - background-position: -216px -48px; -} - -.icon-text-width { - background-position: -240px -48px; -} - -.icon-align-left { - background-position: -264px -48px; -} - -.icon-align-center { - background-position: -288px -48px; -} - -.icon-align-right { - background-position: -312px -48px; -} - -.icon-align-justify { - background-position: -336px -48px; -} - -.icon-list { - background-position: -360px -48px; -} - -.icon-indent-left { - background-position: -384px -48px; -} - -.icon-indent-right { - background-position: -408px -48px; -} - -.icon-facetime-video { - background-position: -432px -48px; -} - -.icon-picture { - background-position: -456px -48px; -} - -.icon-pencil { - background-position: 0 -72px; -} - -.icon-map-marker { - background-position: -24px -72px; -} - -.icon-adjust { - background-position: -48px -72px; -} - -.icon-tint { - background-position: -72px -72px; -} - -.icon-edit { - background-position: -96px -72px; -} - -.icon-share { - background-position: -120px -72px; -} - -.icon-check { - background-position: -144px -72px; -} - -.icon-move { - background-position: -168px -72px; -} - -.icon-step-backward { - background-position: -192px -72px; -} - -.icon-fast-backward { - background-position: -216px -72px; -} - -.icon-backward { - background-position: -240px -72px; -} - -.icon-play { - background-position: -264px -72px; -} - -.icon-pause { - background-position: -288px -72px; -} - -.icon-stop { - background-position: -312px -72px; -} - -.icon-forward { - background-position: -336px -72px; -} - -.icon-fast-forward { - background-position: -360px -72px; -} - -.icon-step-forward { - background-position: -384px -72px; -} - -.icon-eject { - background-position: -408px -72px; -} - -.icon-chevron-left { - background-position: -432px -72px; -} - -.icon-chevron-right { - background-position: -456px -72px; -} - -.icon-plus-sign { - background-position: 0 -96px; -} - -.icon-minus-sign { - background-position: -24px -96px; -} - -.icon-remove-sign { - background-position: -48px -96px; -} - -.icon-ok-sign { - background-position: -72px -96px; -} - -.icon-question-sign { - background-position: -96px -96px; -} - -.icon-info-sign { - background-position: -120px -96px; -} - -.icon-screenshot { - background-position: -144px -96px; -} - -.icon-remove-circle { - background-position: -168px -96px; -} - -.icon-ok-circle { - background-position: -192px -96px; -} - -.icon-ban-circle { - background-position: -216px -96px; -} - -.icon-arrow-left { - background-position: -240px -96px; -} - -.icon-arrow-right { - background-position: -264px -96px; -} - -.icon-arrow-up { - background-position: -289px -96px; -} - -.icon-arrow-down { - background-position: -312px -96px; -} - -.icon-share-alt { - background-position: -336px -96px; -} - -.icon-resize-full { - background-position: -360px -96px; -} - -.icon-resize-small { - background-position: -384px -96px; -} - -.icon-plus { - background-position: -408px -96px; -} - -.icon-minus { - background-position: -433px -96px; -} - -.icon-asterisk { - background-position: -456px -96px; -} - -.icon-exclamation-sign { - background-position: 0 -120px; -} - -.icon-gift { - background-position: -24px -120px; -} - -.icon-leaf { - background-position: -48px -120px; -} - -.icon-fire { - background-position: -72px -120px; -} - -.icon-eye-open { - background-position: -96px -120px; -} - -.icon-eye-close { - background-position: -120px -120px; -} - -.icon-warning-sign { - background-position: -144px -120px; -} - -.icon-plane { - background-position: -168px -120px; -} - -.icon-calendar { - background-position: -192px -120px; -} - -.icon-random { - width: 16px; - background-position: -216px -120px; -} - -.icon-comment { - background-position: -240px -120px; -} - -.icon-magnet { - background-position: -264px -120px; -} - -.icon-chevron-up { - background-position: -288px -120px; -} - -.icon-chevron-down { - background-position: -313px -119px; -} - -.icon-retweet { - background-position: -336px -120px; -} - -.icon-shopping-cart { - background-position: -360px -120px; -} - -.icon-folder-close { - width: 16px; - background-position: -384px -120px; -} - -.icon-folder-open { - width: 16px; - background-position: -408px -120px; -} - -.icon-resize-vertical { - background-position: -432px -119px; -} - -.icon-resize-horizontal { - background-position: -456px -118px; -} - -.icon-hdd { - background-position: 0 -144px; -} - -.icon-bullhorn { - background-position: -24px -144px; -} - -.icon-bell { - background-position: -48px -144px; -} - -.icon-certificate { - background-position: -72px -144px; -} - -.icon-thumbs-up { - background-position: -96px -144px; -} - -.icon-thumbs-down { - background-position: -120px -144px; -} - -.icon-hand-right { - background-position: -144px -144px; -} - -.icon-hand-left { - background-position: -168px -144px; -} - -.icon-hand-up { - background-position: -192px -144px; -} - -.icon-hand-down { - background-position: -216px -144px; -} - -.icon-circle-arrow-right { - background-position: -240px -144px; -} - -.icon-circle-arrow-left { - background-position: -264px -144px; -} - -.icon-circle-arrow-up { - background-position: -288px -144px; -} - -.icon-circle-arrow-down { - background-position: -312px -144px; -} - -.icon-globe { - background-position: -336px -144px; -} - -.icon-wrench { - background-position: -360px -144px; -} - -.icon-tasks { - background-position: -384px -144px; -} - -.icon-filter { - background-position: -408px -144px; -} - -.icon-briefcase { - background-position: -432px -144px; -} - -.icon-fullscreen { - background-position: -456px -144px; -} - -.dropup, -.dropdown { - position: relative; -} - -.dropdown-toggle { - *margin-bottom: -3px; -} - -.dropdown-toggle:active, -.open .dropdown-toggle { - outline: 0; -} - -.caret { - display: inline-block; - width: 0; - height: 0; - vertical-align: top; - border-top: 4px solid #000000; - border-right: 4px solid transparent; - border-left: 4px solid transparent; - content: ""; -} - -.dropdown .caret { - margin-top: 8px; - margin-left: 2px; -} - -.dropdown-menu { - position: absolute; - top: 100%; - left: 0; - z-index: 1000; - display: none; - float: left; - min-width: 160px; - padding: 5px 0; - margin: 2px 0 0; - list-style: none; - background-color: #ffffff; - border: 1px solid #ccc; - border: 1px solid rgba(0, 0, 0, 0.2); - *border-right-width: 2px; - *border-bottom-width: 2px; - -webkit-border-radius: 6px; - -moz-border-radius: 6px; - border-radius: 6px; - -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); - -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); - box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); - -webkit-background-clip: padding-box; - -moz-background-clip: padding; - background-clip: padding-box; -} - -.dropdown-menu.pull-right { - right: 0; - left: auto; -} - -.dropdown-menu .divider { - *width: 100%; - height: 1px; - margin: 9px 1px; - *margin: -5px 0 5px; - overflow: hidden; - background-color: #e5e5e5; - border-bottom: 1px solid #ffffff; -} - -.dropdown-menu > li > a { - display: block; - padding: 3px 20px; - clear: both; - font-weight: normal; - line-height: 20px; - color: #333333; - white-space: nowrap; -} - -.dropdown-menu > li > a:hover, -.dropdown-menu > li > a:focus, -.dropdown-submenu:hover > a, -.dropdown-submenu:focus > a { - color: #ffffff; - text-decoration: none; - background-color: #0081c2; - background-image: -moz-linear-gradient(top, #0088cc, #0077b3); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3)); - background-image: -webkit-linear-gradient(top, #0088cc, #0077b3); - background-image: -o-linear-gradient(top, #0088cc, #0077b3); - background-image: linear-gradient(to bottom, #0088cc, #0077b3); - background-repeat: repeat-x; - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0); -} - -.dropdown-menu > .active > a, -.dropdown-menu > .active > a:hover, -.dropdown-menu > .active > a:focus { - color: #ffffff; - text-decoration: none; - background-color: #0081c2; - background-image: -moz-linear-gradient(top, #0088cc, #0077b3); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3)); - background-image: -webkit-linear-gradient(top, #0088cc, #0077b3); - background-image: -o-linear-gradient(top, #0088cc, #0077b3); - background-image: linear-gradient(to bottom, #0088cc, #0077b3); - background-repeat: repeat-x; - outline: 0; - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0); -} - -.dropdown-menu > .disabled > a, -.dropdown-menu > .disabled > a:hover, -.dropdown-menu > .disabled > a:focus { - color: #999999; -} - -.dropdown-menu > .disabled > a:hover, -.dropdown-menu > .disabled > a:focus { - text-decoration: none; - cursor: default; - background-color: transparent; - background-image: none; - filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); -} - -.open { - *z-index: 1000; -} - -.open > .dropdown-menu { - display: block; -} - -.pull-right > .dropdown-menu { - right: 0; - left: auto; -} - -.dropup .caret, -.navbar-fixed-bottom .dropdown .caret { - border-top: 0; - border-bottom: 4px solid #000000; - content: ""; -} - -.dropup .dropdown-menu, -.navbar-fixed-bottom .dropdown .dropdown-menu { - top: auto; - bottom: 100%; - margin-bottom: 1px; -} - -.dropdown-submenu { - position: relative; -} - -.dropdown-submenu > .dropdown-menu { - top: 0; - left: 100%; - margin-top: -6px; - margin-left: -1px; - -webkit-border-radius: 0 6px 6px 6px; - -moz-border-radius: 0 6px 6px 6px; - border-radius: 0 6px 6px 6px; -} - -.dropdown-submenu:hover > .dropdown-menu { - display: block; -} - -.dropup .dropdown-submenu > .dropdown-menu { - top: auto; - bottom: 0; - margin-top: 0; - margin-bottom: -2px; - -webkit-border-radius: 5px 5px 5px 0; - -moz-border-radius: 5px 5px 5px 0; - border-radius: 5px 5px 5px 0; -} - -.dropdown-submenu > a:after { - display: block; - float: right; - width: 0; - height: 0; - margin-top: 5px; - margin-right: -10px; - border-color: transparent; - border-left-color: #cccccc; - border-style: solid; - border-width: 5px 0 5px 5px; - content: " "; -} - -.dropdown-submenu:hover > a:after { - border-left-color: #ffffff; -} - -.dropdown-submenu.pull-left { - float: none; -} - -.dropdown-submenu.pull-left > .dropdown-menu { - left: -100%; - margin-left: 10px; - -webkit-border-radius: 6px 0 6px 6px; - -moz-border-radius: 6px 0 6px 6px; - border-radius: 6px 0 6px 6px; -} - -.dropdown .dropdown-menu .nav-header { - padding-right: 20px; - padding-left: 20px; -} - -.typeahead { - z-index: 1051; - margin-top: 2px; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; -} - -.well { - min-height: 20px; - padding: 19px; - margin-bottom: 20px; - background-color: #f5f5f5; - border: 1px solid #e3e3e3; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); - -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); - box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); -} - -.well blockquote { - border-color: #ddd; - border-color: rgba(0, 0, 0, 0.15); -} - -.well-large { - padding: 24px; - -webkit-border-radius: 6px; - -moz-border-radius: 6px; - border-radius: 6px; -} - -.well-small { - padding: 9px; - -webkit-border-radius: 3px; - -moz-border-radius: 3px; - border-radius: 3px; -} - -.fade { - opacity: 0; - -webkit-transition: opacity 0.15s linear; - -moz-transition: opacity 0.15s linear; - -o-transition: opacity 0.15s linear; - transition: opacity 0.15s linear; -} - -.fade.in { - opacity: 1; -} - -.collapse { - position: relative; - height: 0; - overflow: hidden; - -webkit-transition: height 0.35s ease; - -moz-transition: height 0.35s ease; - -o-transition: height 0.35s ease; - transition: height 0.35s ease; -} - -.collapse.in { - height: auto; -} - -.close { - float: right; - font-size: 20px; - font-weight: bold; - line-height: 20px; - color: #000000; - text-shadow: 0 1px 0 #ffffff; - opacity: 0.2; - filter: alpha(opacity=20); -} - -.close:hover, -.close:focus { - color: #000000; - text-decoration: none; - cursor: pointer; - opacity: 0.4; - filter: alpha(opacity=40); -} - -button.close { - padding: 0; - cursor: pointer; - background: transparent; - border: 0; - -webkit-appearance: none; -} - -.btn { - display: inline-block; - *display: inline; - padding: 4px 12px; - margin-bottom: 0; - *margin-left: .3em; - font-size: 14px; - line-height: 20px; - color: #333333; - text-align: center; - text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75); - vertical-align: middle; - cursor: pointer; - background-color: #f5f5f5; - *background-color: #e6e6e6; - background-image: -moz-linear-gradient(top, #ffffff, #e6e6e6); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#e6e6e6)); - background-image: -webkit-linear-gradient(top, #ffffff, #e6e6e6); - background-image: -o-linear-gradient(top, #ffffff, #e6e6e6); - background-image: linear-gradient(to bottom, #ffffff, #e6e6e6); - background-repeat: repeat-x; - border: 1px solid #cccccc; - *border: 0; - border-color: #e6e6e6 #e6e6e6 #bfbfbf; - border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); - border-bottom-color: #b3b3b3; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe6e6e6', GradientType=0); - filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); - *zoom: 1; - -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); - -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); - box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); -} - -.btn:hover, -.btn:focus, -.btn:active, -.btn.active, -.btn.disabled, -.btn[disabled] { - color: #333333; - background-color: #e6e6e6; - *background-color: #d9d9d9; -} - -.btn:active, -.btn.active { - background-color: #cccccc \9; -} - -.btn:first-child { - *margin-left: 0; -} - -.btn:hover, -.btn:focus { - color: #333333; - text-decoration: none; - background-position: 0 -15px; - -webkit-transition: background-position 0.1s linear; - -moz-transition: background-position 0.1s linear; - -o-transition: background-position 0.1s linear; - transition: background-position 0.1s linear; -} - -.btn:focus { - outline: thin dotted #333; - outline: 5px auto -webkit-focus-ring-color; - outline-offset: -2px; -} - -.btn.active, -.btn:active { - background-image: none; - outline: 0; - -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); - -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); - box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); -} - -.btn.disabled, -.btn[disabled] { - cursor: default; - background-image: none; - opacity: 0.65; - filter: alpha(opacity=65); - -webkit-box-shadow: none; - -moz-box-shadow: none; - box-shadow: none; -} - -.btn-large { - padding: 11px 19px; - font-size: 17.5px; - -webkit-border-radius: 6px; - -moz-border-radius: 6px; - border-radius: 6px; -} - -.btn-large [class^="icon-"], -.btn-large [class*=" icon-"] { - margin-top: 4px; -} - -.btn-small { - padding: 2px 10px; - font-size: 11.9px; - -webkit-border-radius: 3px; - -moz-border-radius: 3px; - border-radius: 3px; -} - -.btn-small [class^="icon-"], -.btn-small [class*=" icon-"] { - margin-top: 0; -} - -.btn-mini [class^="icon-"], -.btn-mini [class*=" icon-"] { - margin-top: -1px; -} - -.btn-mini { - padding: 0 6px; - font-size: 10.5px; - -webkit-border-radius: 3px; - -moz-border-radius: 3px; - border-radius: 3px; -} - -.btn-block { - display: block; - width: 100%; - padding-right: 0; - padding-left: 0; - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; -} - -.btn-block + .btn-block { - margin-top: 5px; -} - -input[type="submit"].btn-block, -input[type="reset"].btn-block, -input[type="button"].btn-block { - width: 100%; -} - -.btn-primary.active, -.btn-warning.active, -.btn-danger.active, -.btn-success.active, -.btn-info.active, -.btn-inverse.active { - color: rgba(255, 255, 255, 0.75); -} - -.btn-primary { - color: #ffffff; - text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); - background-color: #006dcc; - *background-color: #0044cc; - background-image: -moz-linear-gradient(top, #0088cc, #0044cc); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc)); - background-image: -webkit-linear-gradient(top, #0088cc, #0044cc); - background-image: -o-linear-gradient(top, #0088cc, #0044cc); - background-image: linear-gradient(to bottom, #0088cc, #0044cc); - background-repeat: repeat-x; - border-color: #0044cc #0044cc #002a80; - border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0044cc', GradientType=0); - filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); -} - -.btn-primary:hover, -.btn-primary:focus, -.btn-primary:active, -.btn-primary.active, -.btn-primary.disabled, -.btn-primary[disabled] { - color: #ffffff; - background-color: #0044cc; - *background-color: #003bb3; -} - -.btn-primary:active, -.btn-primary.active { - background-color: #003399 \9; -} - -.btn-warning { - color: #ffffff; - text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); - background-color: #faa732; - *background-color: #f89406; - background-image: -moz-linear-gradient(top, #fbb450, #f89406); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406)); - background-image: -webkit-linear-gradient(top, #fbb450, #f89406); - background-image: -o-linear-gradient(top, #fbb450, #f89406); - background-image: linear-gradient(to bottom, #fbb450, #f89406); - background-repeat: repeat-x; - border-color: #f89406 #f89406 #ad6704; - border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0); - filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); -} - -.btn-warning:hover, -.btn-warning:focus, -.btn-warning:active, -.btn-warning.active, -.btn-warning.disabled, -.btn-warning[disabled] { - color: #ffffff; - background-color: #f89406; - *background-color: #df8505; -} - -.btn-warning:active, -.btn-warning.active { - background-color: #c67605 \9; -} - -.btn-danger { - color: #ffffff; - text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); - background-color: #da4f49; - *background-color: #bd362f; - background-image: -moz-linear-gradient(top, #ee5f5b, #bd362f); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#bd362f)); - background-image: -webkit-linear-gradient(top, #ee5f5b, #bd362f); - background-image: -o-linear-gradient(top, #ee5f5b, #bd362f); - background-image: linear-gradient(to bottom, #ee5f5b, #bd362f); - background-repeat: repeat-x; - border-color: #bd362f #bd362f #802420; - border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffbd362f', GradientType=0); - filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); -} - -.btn-danger:hover, -.btn-danger:focus, -.btn-danger:active, -.btn-danger.active, -.btn-danger.disabled, -.btn-danger[disabled] { - color: #ffffff; - background-color: #bd362f; - *background-color: #a9302a; -} - -.btn-danger:active, -.btn-danger.active { - background-color: #942a25 \9; -} - -.btn-success { - color: #ffffff; - text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); - background-color: #5bb75b; - *background-color: #51a351; - background-image: -moz-linear-gradient(top, #62c462, #51a351); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#51a351)); - background-image: -webkit-linear-gradient(top, #62c462, #51a351); - background-image: -o-linear-gradient(top, #62c462, #51a351); - background-image: linear-gradient(to bottom, #62c462, #51a351); - background-repeat: repeat-x; - border-color: #51a351 #51a351 #387038; - border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff51a351', GradientType=0); - filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); -} - -.btn-success:hover, -.btn-success:focus, -.btn-success:active, -.btn-success.active, -.btn-success.disabled, -.btn-success[disabled] { - color: #ffffff; - background-color: #51a351; - *background-color: #499249; -} - -.btn-success:active, -.btn-success.active { - background-color: #408140 \9; -} - -.btn-info { - color: #ffffff; - text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); - background-color: #49afcd; - *background-color: #2f96b4; - background-image: -moz-linear-gradient(top, #5bc0de, #2f96b4); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#2f96b4)); - background-image: -webkit-linear-gradient(top, #5bc0de, #2f96b4); - background-image: -o-linear-gradient(top, #5bc0de, #2f96b4); - background-image: linear-gradient(to bottom, #5bc0de, #2f96b4); - background-repeat: repeat-x; - border-color: #2f96b4 #2f96b4 #1f6377; - border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2f96b4', GradientType=0); - filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); -} - -.btn-info:hover, -.btn-info:focus, -.btn-info:active, -.btn-info.active, -.btn-info.disabled, -.btn-info[disabled] { - color: #ffffff; - background-color: #2f96b4; - *background-color: #2a85a0; -} - -.btn-info:active, -.btn-info.active { - background-color: #24748c \9; -} - -.btn-inverse { - color: #ffffff; - text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); - background-color: #363636; - *background-color: #222222; - background-image: -moz-linear-gradient(top, #444444, #222222); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#444444), to(#222222)); - background-image: -webkit-linear-gradient(top, #444444, #222222); - background-image: -o-linear-gradient(top, #444444, #222222); - background-image: linear-gradient(to bottom, #444444, #222222); - background-repeat: repeat-x; - border-color: #222222 #222222 #000000; - border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff444444', endColorstr='#ff222222', GradientType=0); - filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); -} - -.btn-inverse:hover, -.btn-inverse:focus, -.btn-inverse:active, -.btn-inverse.active, -.btn-inverse.disabled, -.btn-inverse[disabled] { - color: #ffffff; - background-color: #222222; - *background-color: #151515; -} - -.btn-inverse:active, -.btn-inverse.active { - background-color: #080808 \9; -} - -button.btn, -input[type="submit"].btn { - *padding-top: 3px; - *padding-bottom: 3px; -} - -button.btn::-moz-focus-inner, -input[type="submit"].btn::-moz-focus-inner { - padding: 0; - border: 0; -} - -button.btn.btn-large, -input[type="submit"].btn.btn-large { - *padding-top: 7px; - *padding-bottom: 7px; -} - -button.btn.btn-small, -input[type="submit"].btn.btn-small { - *padding-top: 3px; - *padding-bottom: 3px; -} - -button.btn.btn-mini, -input[type="submit"].btn.btn-mini { - *padding-top: 1px; - *padding-bottom: 1px; -} - -.btn-link, -.btn-link:active, -.btn-link[disabled] { - background-color: transparent; - background-image: none; - -webkit-box-shadow: none; - -moz-box-shadow: none; - box-shadow: none; -} - -.btn-link { - color: #0088cc; - cursor: pointer; - border-color: transparent; - -webkit-border-radius: 0; - -moz-border-radius: 0; - border-radius: 0; -} - -.btn-link:hover, -.btn-link:focus { - color: #005580; - text-decoration: underline; - background-color: transparent; -} - -.btn-link[disabled]:hover, -.btn-link[disabled]:focus { - color: #333333; - text-decoration: none; -} - -.btn-group { - position: relative; - display: inline-block; - *display: inline; - *margin-left: .3em; - font-size: 0; - white-space: nowrap; - vertical-align: middle; - *zoom: 1; -} - -.btn-group:first-child { - *margin-left: 0; -} - -.btn-group + .btn-group { - margin-left: 5px; -} - -.btn-toolbar { - margin-top: 10px; - margin-bottom: 10px; - font-size: 0; -} - -.btn-toolbar > .btn + .btn, -.btn-toolbar > .btn-group + .btn, -.btn-toolbar > .btn + .btn-group { - margin-left: 5px; -} - -.btn-group > .btn { - position: relative; - -webkit-border-radius: 0; - -moz-border-radius: 0; - border-radius: 0; -} - -.btn-group > .btn + .btn { - margin-left: -1px; -} - -.btn-group > .btn, -.btn-group > .dropdown-menu, -.btn-group > .popover { - font-size: 14px; -} - -.btn-group > .btn-mini { - font-size: 10.5px; -} - -.btn-group > .btn-small { - font-size: 11.9px; -} - -.btn-group > .btn-large { - font-size: 17.5px; -} - -.btn-group > .btn:first-child { - margin-left: 0; - -webkit-border-bottom-left-radius: 4px; - border-bottom-left-radius: 4px; - -webkit-border-top-left-radius: 4px; - border-top-left-radius: 4px; - -moz-border-radius-bottomleft: 4px; - -moz-border-radius-topleft: 4px; -} - -.btn-group > .btn:last-child, -.btn-group > .dropdown-toggle { - -webkit-border-top-right-radius: 4px; - border-top-right-radius: 4px; - -webkit-border-bottom-right-radius: 4px; - border-bottom-right-radius: 4px; - -moz-border-radius-topright: 4px; - -moz-border-radius-bottomright: 4px; -} - -.btn-group > .btn.large:first-child { - margin-left: 0; - -webkit-border-bottom-left-radius: 6px; - border-bottom-left-radius: 6px; - -webkit-border-top-left-radius: 6px; - border-top-left-radius: 6px; - -moz-border-radius-bottomleft: 6px; - -moz-border-radius-topleft: 6px; -} - -.btn-group > .btn.large:last-child, -.btn-group > .large.dropdown-toggle { - -webkit-border-top-right-radius: 6px; - border-top-right-radius: 6px; - -webkit-border-bottom-right-radius: 6px; - border-bottom-right-radius: 6px; - -moz-border-radius-topright: 6px; - -moz-border-radius-bottomright: 6px; -} - -.btn-group > .btn:hover, -.btn-group > .btn:focus, -.btn-group > .btn:active, -.btn-group > .btn.active { - z-index: 2; -} - -.btn-group .dropdown-toggle:active, -.btn-group.open .dropdown-toggle { - outline: 0; -} - -.btn-group > .btn + .dropdown-toggle { - *padding-top: 5px; - padding-right: 8px; - *padding-bottom: 5px; - padding-left: 8px; - -webkit-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); - -moz-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); - box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); -} - -.btn-group > .btn-mini + .dropdown-toggle { - *padding-top: 2px; - padding-right: 5px; - *padding-bottom: 2px; - padding-left: 5px; -} - -.btn-group > .btn-small + .dropdown-toggle { - *padding-top: 5px; - *padding-bottom: 4px; -} - -.btn-group > .btn-large + .dropdown-toggle { - *padding-top: 7px; - padding-right: 12px; - *padding-bottom: 7px; - padding-left: 12px; -} - -.btn-group.open .dropdown-toggle { - background-image: none; - -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); - -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); - box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); -} - -.btn-group.open .btn.dropdown-toggle { - background-color: #e6e6e6; -} - -.btn-group.open .btn-primary.dropdown-toggle { - background-color: #0044cc; -} - -.btn-group.open .btn-warning.dropdown-toggle { - background-color: #f89406; -} - -.btn-group.open .btn-danger.dropdown-toggle { - background-color: #bd362f; -} - -.btn-group.open .btn-success.dropdown-toggle { - background-color: #51a351; -} - -.btn-group.open .btn-info.dropdown-toggle { - background-color: #2f96b4; -} - -.btn-group.open .btn-inverse.dropdown-toggle { - background-color: #222222; -} - -.btn .caret { - margin-top: 8px; - margin-left: 0; -} - -.btn-large .caret { - margin-top: 6px; -} - -.btn-large .caret { - border-top-width: 5px; - border-right-width: 5px; - border-left-width: 5px; -} - -.btn-mini .caret, -.btn-small .caret { - margin-top: 8px; -} - -.dropup .btn-large .caret { - border-bottom-width: 5px; -} - -.btn-primary .caret, -.btn-warning .caret, -.btn-danger .caret, -.btn-info .caret, -.btn-success .caret, -.btn-inverse .caret { - border-top-color: #ffffff; - border-bottom-color: #ffffff; -} - -.btn-group-vertical { - display: inline-block; - *display: inline; - /* IE7 inline-block hack */ - - *zoom: 1; -} - -.btn-group-vertical > .btn { - display: block; - float: none; - max-width: 100%; - -webkit-border-radius: 0; - -moz-border-radius: 0; - border-radius: 0; -} - -.btn-group-vertical > .btn + .btn { - margin-top: -1px; - margin-left: 0; -} - -.btn-group-vertical > .btn:first-child { - -webkit-border-radius: 4px 4px 0 0; - -moz-border-radius: 4px 4px 0 0; - border-radius: 4px 4px 0 0; -} - -.btn-group-vertical > .btn:last-child { - -webkit-border-radius: 0 0 4px 4px; - -moz-border-radius: 0 0 4px 4px; - border-radius: 0 0 4px 4px; -} - -.btn-group-vertical > .btn-large:first-child { - -webkit-border-radius: 6px 6px 0 0; - -moz-border-radius: 6px 6px 0 0; - border-radius: 6px 6px 0 0; -} - -.btn-group-vertical > .btn-large:last-child { - -webkit-border-radius: 0 0 6px 6px; - -moz-border-radius: 0 0 6px 6px; - border-radius: 0 0 6px 6px; -} - -.alert { - padding: 8px 35px 8px 14px; - margin-bottom: 20px; - text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); - background-color: #fcf8e3; - border: 1px solid #fbeed5; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; -} - -.alert, -.alert h4 { - color: #c09853; -} - -.alert h4 { - margin: 0; -} - -.alert .close { - position: relative; - top: -2px; - right: -21px; - line-height: 20px; -} - -.alert-success { - color: #468847; - background-color: #dff0d8; - border-color: #d6e9c6; -} - -.alert-success h4 { - color: #468847; -} - -.alert-danger, -.alert-error { - color: #b94a48; - background-color: #f2dede; - border-color: #eed3d7; -} - -.alert-danger h4, -.alert-error h4 { - color: #b94a48; -} - -.alert-info { - color: #3a87ad; - background-color: #d9edf7; - border-color: #bce8f1; -} - -.alert-info h4 { - color: #3a87ad; -} - -.alert-block { - padding-top: 14px; - padding-bottom: 14px; -} - -.alert-block > p, -.alert-block > ul { - margin-bottom: 0; -} - -.alert-block p + p { - margin-top: 5px; -} - -.nav { - margin-bottom: 20px; - margin-left: 0; - list-style: none; -} - -.nav > li > a { - display: block; -} - -.nav > li > a:hover, -.nav > li > a:focus { - text-decoration: none; - background-color: #eeeeee; -} - -.nav > li > a > img { - max-width: none; -} - -.nav > .pull-right { - float: right; -} - -.nav-header { - display: block; - padding: 3px 15px; - font-size: 11px; - font-weight: bold; - line-height: 20px; - color: #999999; - text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); - text-transform: uppercase; -} - -.nav li + .nav-header { - margin-top: 9px; -} - -.nav-list { - padding-right: 15px; - padding-left: 15px; - margin-bottom: 0; -} - -.nav-list > li > a, -.nav-list .nav-header { - margin-right: -15px; - margin-left: -15px; - text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); -} - -.nav-list > li > a { - padding: 3px 15px; -} - -.nav-list > .active > a, -.nav-list > .active > a:hover, -.nav-list > .active > a:focus { - color: #ffffff; - text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2); - background-color: #0088cc; -} - -.nav-list [class^="icon-"], -.nav-list [class*=" icon-"] { - margin-right: 2px; -} - -.nav-list .divider { - *width: 100%; - height: 1px; - margin: 9px 1px; - *margin: -5px 0 5px; - overflow: hidden; - background-color: #e5e5e5; - border-bottom: 1px solid #ffffff; -} - -.nav-tabs, -.nav-pills { - *zoom: 1; -} - -.nav-tabs:before, -.nav-pills:before, -.nav-tabs:after, -.nav-pills:after { - display: table; - line-height: 0; - content: ""; -} - -.nav-tabs:after, -.nav-pills:after { - clear: both; -} - -.nav-tabs > li, -.nav-pills > li { - float: left; -} - -.nav-tabs > li > a, -.nav-pills > li > a { - padding-right: 12px; - padding-left: 12px; - margin-right: 2px; - line-height: 14px; -} - -.nav-tabs { - border-bottom: 1px solid #ddd; -} - -.nav-tabs > li { - margin-bottom: -1px; -} - -.nav-tabs > li > a { - padding-top: 8px; - padding-bottom: 8px; - line-height: 20px; - border: 1px solid transparent; - -webkit-border-radius: 4px 4px 0 0; - -moz-border-radius: 4px 4px 0 0; - border-radius: 4px 4px 0 0; -} - -.nav-tabs > li > a:hover, -.nav-tabs > li > a:focus { - border-color: #eeeeee #eeeeee #dddddd; -} - -.nav-tabs > .active > a, -.nav-tabs > .active > a:hover, -.nav-tabs > .active > a:focus { - color: #555555; - cursor: default; - background-color: #ffffff; - border: 1px solid #ddd; - border-bottom-color: transparent; -} - -.nav-pills > li > a { - padding-top: 8px; - padding-bottom: 8px; - margin-top: 2px; - margin-bottom: 2px; - -webkit-border-radius: 5px; - -moz-border-radius: 5px; - border-radius: 5px; -} - -.nav-pills > .active > a, -.nav-pills > .active > a:hover, -.nav-pills > .active > a:focus { - color: #ffffff; - background-color: #0088cc; -} - -.nav-stacked > li { - float: none; -} - -.nav-stacked > li > a { - margin-right: 0; -} - -.nav-tabs.nav-stacked { - border-bottom: 0; -} - -.nav-tabs.nav-stacked > li > a { - border: 1px solid #ddd; - -webkit-border-radius: 0; - -moz-border-radius: 0; - border-radius: 0; -} - -.nav-tabs.nav-stacked > li:first-child > a { - -webkit-border-top-right-radius: 4px; - border-top-right-radius: 4px; - -webkit-border-top-left-radius: 4px; - border-top-left-radius: 4px; - -moz-border-radius-topright: 4px; - -moz-border-radius-topleft: 4px; -} - -.nav-tabs.nav-stacked > li:last-child > a { - -webkit-border-bottom-right-radius: 4px; - border-bottom-right-radius: 4px; - -webkit-border-bottom-left-radius: 4px; - border-bottom-left-radius: 4px; - -moz-border-radius-bottomright: 4px; - -moz-border-radius-bottomleft: 4px; -} - -.nav-tabs.nav-stacked > li > a:hover, -.nav-tabs.nav-stacked > li > a:focus { - z-index: 2; - border-color: #ddd; -} - -.nav-pills.nav-stacked > li > a { - margin-bottom: 3px; -} - -.nav-pills.nav-stacked > li:last-child > a { - margin-bottom: 1px; -} - -.nav-tabs .dropdown-menu { - -webkit-border-radius: 0 0 6px 6px; - -moz-border-radius: 0 0 6px 6px; - border-radius: 0 0 6px 6px; -} - -.nav-pills .dropdown-menu { - -webkit-border-radius: 6px; - -moz-border-radius: 6px; - border-radius: 6px; -} - -.nav .dropdown-toggle .caret { - margin-top: 6px; - border-top-color: #0088cc; - border-bottom-color: #0088cc; -} - -.nav .dropdown-toggle:hover .caret, -.nav .dropdown-toggle:focus .caret { - border-top-color: #005580; - border-bottom-color: #005580; -} - -/* move down carets for tabs */ - -.nav-tabs .dropdown-toggle .caret { - margin-top: 8px; -} - -.nav .active .dropdown-toggle .caret { - border-top-color: #fff; - border-bottom-color: #fff; -} - -.nav-tabs .active .dropdown-toggle .caret { - border-top-color: #555555; - border-bottom-color: #555555; -} - -.nav > .dropdown.active > a:hover, -.nav > .dropdown.active > a:focus { - cursor: pointer; -} - -.nav-tabs .open .dropdown-toggle, -.nav-pills .open .dropdown-toggle, -.nav > li.dropdown.open.active > a:hover, -.nav > li.dropdown.open.active > a:focus { - color: #ffffff; - background-color: #999999; - border-color: #999999; -} - -.nav li.dropdown.open .caret, -.nav li.dropdown.open.active .caret, -.nav li.dropdown.open a:hover .caret, -.nav li.dropdown.open a:focus .caret { - border-top-color: #ffffff; - border-bottom-color: #ffffff; - opacity: 1; - filter: alpha(opacity=100); -} - -.tabs-stacked .open > a:hover, -.tabs-stacked .open > a:focus { - border-color: #999999; -} - -.tabbable { - *zoom: 1; -} - -.tabbable:before, -.tabbable:after { - display: table; - line-height: 0; - content: ""; -} - -.tabbable:after { - clear: both; -} - -.tab-content { - overflow: auto; -} - -.tabs-below > .nav-tabs, -.tabs-right > .nav-tabs, -.tabs-left > .nav-tabs { - border-bottom: 0; -} - -.tab-content > .tab-pane, -.pill-content > .pill-pane { - display: none; -} - -.tab-content > .active, -.pill-content > .active { - display: block; -} - -.tabs-below > .nav-tabs { - border-top: 1px solid #ddd; -} - -.tabs-below > .nav-tabs > li { - margin-top: -1px; - margin-bottom: 0; -} - -.tabs-below > .nav-tabs > li > a { - -webkit-border-radius: 0 0 4px 4px; - -moz-border-radius: 0 0 4px 4px; - border-radius: 0 0 4px 4px; -} - -.tabs-below > .nav-tabs > li > a:hover, -.tabs-below > .nav-tabs > li > a:focus { - border-top-color: #ddd; - border-bottom-color: transparent; -} - -.tabs-below > .nav-tabs > .active > a, -.tabs-below > .nav-tabs > .active > a:hover, -.tabs-below > .nav-tabs > .active > a:focus { - border-color: transparent #ddd #ddd #ddd; -} - -.tabs-left > .nav-tabs > li, -.tabs-right > .nav-tabs > li { - float: none; -} - -.tabs-left > .nav-tabs > li > a, -.tabs-right > .nav-tabs > li > a { - min-width: 74px; - margin-right: 0; - margin-bottom: 3px; -} - -.tabs-left > .nav-tabs { - float: left; - margin-right: 19px; - border-right: 1px solid #ddd; -} - -.tabs-left > .nav-tabs > li > a { - margin-right: -1px; - -webkit-border-radius: 4px 0 0 4px; - -moz-border-radius: 4px 0 0 4px; - border-radius: 4px 0 0 4px; -} - -.tabs-left > .nav-tabs > li > a:hover, -.tabs-left > .nav-tabs > li > a:focus { - border-color: #eeeeee #dddddd #eeeeee #eeeeee; -} - -.tabs-left > .nav-tabs .active > a, -.tabs-left > .nav-tabs .active > a:hover, -.tabs-left > .nav-tabs .active > a:focus { - border-color: #ddd transparent #ddd #ddd; - *border-right-color: #ffffff; -} - -.tabs-right > .nav-tabs { - float: right; - margin-left: 19px; - border-left: 1px solid #ddd; -} - -.tabs-right > .nav-tabs > li > a { - margin-left: -1px; - -webkit-border-radius: 0 4px 4px 0; - -moz-border-radius: 0 4px 4px 0; - border-radius: 0 4px 4px 0; -} - -.tabs-right > .nav-tabs > li > a:hover, -.tabs-right > .nav-tabs > li > a:focus { - border-color: #eeeeee #eeeeee #eeeeee #dddddd; -} - -.tabs-right > .nav-tabs .active > a, -.tabs-right > .nav-tabs .active > a:hover, -.tabs-right > .nav-tabs .active > a:focus { - border-color: #ddd #ddd #ddd transparent; - *border-left-color: #ffffff; -} - -.nav > .disabled > a { - color: #999999; -} - -.nav > .disabled > a:hover, -.nav > .disabled > a:focus { - text-decoration: none; - cursor: default; - background-color: transparent; -} - -.navbar { - *position: relative; - *z-index: 2; - margin-bottom: 20px; - overflow: visible; -} - -.navbar-inner { - min-height: 40px; - padding-right: 20px; - padding-left: 20px; - background-color: #fafafa; - background-image: -moz-linear-gradient(top, #ffffff, #f2f2f2); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#f2f2f2)); - background-image: -webkit-linear-gradient(top, #ffffff, #f2f2f2); - background-image: -o-linear-gradient(top, #ffffff, #f2f2f2); - background-image: linear-gradient(to bottom, #ffffff, #f2f2f2); - background-repeat: repeat-x; - border: 1px solid #d4d4d4; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff2f2f2', GradientType=0); - *zoom: 1; - -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065); - -moz-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065); - box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065); -} - -.navbar-inner:before, -.navbar-inner:after { - display: table; - line-height: 0; - content: ""; -} - -.navbar-inner:after { - clear: both; -} - -.navbar .container { - width: auto; -} - -.nav-collapse.collapse { - height: auto; - overflow: visible; -} - -.navbar .brand { - display: block; - float: left; - padding: 10px 20px 10px; - margin-left: -20px; - font-size: 20px; - font-weight: 200; - color: #777777; - text-shadow: 0 1px 0 #ffffff; -} - -.navbar .brand:hover, -.navbar .brand:focus { - text-decoration: none; -} - -.navbar-text { - margin-bottom: 0; - line-height: 40px; - color: #777777; -} - -.navbar-link { - color: #777777; -} - -.navbar-link:hover, -.navbar-link:focus { - color: #333333; -} - -.navbar .divider-vertical { - height: 40px; - margin: 0 9px; - border-right: 1px solid #ffffff; - border-left: 1px solid #f2f2f2; -} - -.navbar .btn, -.navbar .btn-group { - margin-top: 5px; -} - -.navbar .btn-group .btn, -.navbar .input-prepend .btn, -.navbar .input-append .btn, -.navbar .input-prepend .btn-group, -.navbar .input-append .btn-group { - margin-top: 0; -} - -.navbar-form { - margin-bottom: 0; - *zoom: 1; -} - -.navbar-form:before, -.navbar-form:after { - display: table; - line-height: 0; - content: ""; -} - -.navbar-form:after { - clear: both; -} - -.navbar-form input, -.navbar-form select, -.navbar-form .radio, -.navbar-form .checkbox { - margin-top: 5px; -} - -.navbar-form input, -.navbar-form select, -.navbar-form .btn { - display: inline-block; - margin-bottom: 0; -} - -.navbar-form input[type="image"], -.navbar-form input[type="checkbox"], -.navbar-form input[type="radio"] { - margin-top: 3px; -} - -.navbar-form .input-append, -.navbar-form .input-prepend { - margin-top: 5px; - white-space: nowrap; -} - -.navbar-form .input-append input, -.navbar-form .input-prepend input { - margin-top: 0; -} - -.navbar-search { - position: relative; - float: left; - margin-top: 5px; - margin-bottom: 0; -} - -.navbar-search .search-query { - padding: 4px 14px; - margin-bottom: 0; - font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; - font-size: 13px; - font-weight: normal; - line-height: 1; - -webkit-border-radius: 15px; - -moz-border-radius: 15px; - border-radius: 15px; -} - -.navbar-static-top { - position: static; - margin-bottom: 0; -} - -.navbar-static-top .navbar-inner { - -webkit-border-radius: 0; - -moz-border-radius: 0; - border-radius: 0; -} - -.navbar-fixed-top, -.navbar-fixed-bottom { - position: fixed; - right: 0; - left: 0; - z-index: 1030; - margin-bottom: 0; -} - -.navbar-fixed-top .navbar-inner, -.navbar-static-top .navbar-inner { - border-width: 0 0 1px; -} - -.navbar-fixed-bottom .navbar-inner { - border-width: 1px 0 0; -} - -.navbar-fixed-top .navbar-inner, -.navbar-fixed-bottom .navbar-inner { - padding-right: 0; - padding-left: 0; - -webkit-border-radius: 0; - -moz-border-radius: 0; - border-radius: 0; -} - -.navbar-static-top .container, -.navbar-fixed-top .container, -.navbar-fixed-bottom .container { - width: 940px; -} - -.navbar-fixed-top { - top: 0; -} - -.navbar-fixed-top .navbar-inner, -.navbar-static-top .navbar-inner { - -webkit-box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1); - -moz-box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1); - box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1); -} - -.navbar-fixed-bottom { - bottom: 0; -} - -.navbar-fixed-bottom .navbar-inner { - -webkit-box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1); - -moz-box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1); - box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1); -} - -.navbar .nav { - position: relative; - left: 0; - display: block; - float: left; - margin: 0 10px 0 0; -} - -.navbar .nav.pull-right { - float: right; - margin-right: 0; -} - -.navbar .nav > li { - float: left; -} - -.navbar .nav > li > a { - float: none; - padding: 10px 15px 10px; - color: #777777; - text-decoration: none; - text-shadow: 0 1px 0 #ffffff; -} - -.navbar .nav .dropdown-toggle .caret { - margin-top: 8px; -} - -.navbar .nav > li > a:focus, -.navbar .nav > li > a:hover { - color: #333333; - text-decoration: none; - background-color: transparent; -} - -.navbar .nav > .active > a, -.navbar .nav > .active > a:hover, -.navbar .nav > .active > a:focus { - color: #555555; - text-decoration: none; - background-color: #e5e5e5; - -webkit-box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125); - -moz-box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125); - box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125); -} - -.navbar .btn-navbar { - display: none; - float: right; - padding: 7px 10px; - margin-right: 5px; - margin-left: 5px; - color: #ffffff; - text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); - background-color: #ededed; - *background-color: #e5e5e5; - background-image: -moz-linear-gradient(top, #f2f2f2, #e5e5e5); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f2f2f2), to(#e5e5e5)); - background-image: -webkit-linear-gradient(top, #f2f2f2, #e5e5e5); - background-image: -o-linear-gradient(top, #f2f2f2, #e5e5e5); - background-image: linear-gradient(to bottom, #f2f2f2, #e5e5e5); - background-repeat: repeat-x; - border-color: #e5e5e5 #e5e5e5 #bfbfbf; - border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2f2f2', endColorstr='#ffe5e5e5', GradientType=0); - filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); - -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075); - -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075); - box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075); -} - -.navbar .btn-navbar:hover, -.navbar .btn-navbar:focus, -.navbar .btn-navbar:active, -.navbar .btn-navbar.active, -.navbar .btn-navbar.disabled, -.navbar .btn-navbar[disabled] { - color: #ffffff; - background-color: #e5e5e5; - *background-color: #d9d9d9; -} - -.navbar .btn-navbar:active, -.navbar .btn-navbar.active { - background-color: #cccccc \9; -} - -.navbar .btn-navbar .icon-bar { - display: block; - width: 18px; - height: 2px; - background-color: #f5f5f5; - -webkit-border-radius: 1px; - -moz-border-radius: 1px; - border-radius: 1px; - -webkit-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25); - -moz-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25); - box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25); -} - -.btn-navbar .icon-bar + .icon-bar { - margin-top: 3px; -} - -.navbar .nav > li > .dropdown-menu:before { - position: absolute; - top: -7px; - left: 9px; - display: inline-block; - border-right: 7px solid transparent; - border-bottom: 7px solid #ccc; - border-left: 7px solid transparent; - border-bottom-color: rgba(0, 0, 0, 0.2); - content: ''; -} - -.navbar .nav > li > .dropdown-menu:after { - position: absolute; - top: -6px; - left: 10px; - display: inline-block; - border-right: 6px solid transparent; - border-bottom: 6px solid #ffffff; - border-left: 6px solid transparent; - content: ''; -} - -.navbar-fixed-bottom .nav > li > .dropdown-menu:before { - top: auto; - bottom: -7px; - border-top: 7px solid #ccc; - border-bottom: 0; - border-top-color: rgba(0, 0, 0, 0.2); -} - -.navbar-fixed-bottom .nav > li > .dropdown-menu:after { - top: auto; - bottom: -6px; - border-top: 6px solid #ffffff; - border-bottom: 0; -} - -.navbar .nav li.dropdown > a:hover .caret, -.navbar .nav li.dropdown > a:focus .caret { - border-top-color: #333333; - border-bottom-color: #333333; -} - -.navbar .nav li.dropdown.open > .dropdown-toggle, -.navbar .nav li.dropdown.active > .dropdown-toggle, -.navbar .nav li.dropdown.open.active > .dropdown-toggle { - color: #555555; - background-color: #e5e5e5; -} - -.navbar .nav li.dropdown > .dropdown-toggle .caret { - border-top-color: #777777; - border-bottom-color: #777777; -} - -.navbar .nav li.dropdown.open > .dropdown-toggle .caret, -.navbar .nav li.dropdown.active > .dropdown-toggle .caret, -.navbar .nav li.dropdown.open.active > .dropdown-toggle .caret { - border-top-color: #555555; - border-bottom-color: #555555; -} - -.navbar .pull-right > li > .dropdown-menu, -.navbar .nav > li > .dropdown-menu.pull-right { - right: 0; - left: auto; -} - -.navbar .pull-right > li > .dropdown-menu:before, -.navbar .nav > li > .dropdown-menu.pull-right:before { - right: 12px; - left: auto; -} - -.navbar .pull-right > li > .dropdown-menu:after, -.navbar .nav > li > .dropdown-menu.pull-right:after { - right: 13px; - left: auto; -} - -.navbar .pull-right > li > .dropdown-menu .dropdown-menu, -.navbar .nav > li > .dropdown-menu.pull-right .dropdown-menu { - right: 100%; - left: auto; - margin-right: -1px; - margin-left: 0; - -webkit-border-radius: 6px 0 6px 6px; - -moz-border-radius: 6px 0 6px 6px; - border-radius: 6px 0 6px 6px; -} - -.navbar-inverse .navbar-inner { - background-color: #1b1b1b; - background-image: -moz-linear-gradient(top, #222222, #111111); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#222222), to(#111111)); - background-image: -webkit-linear-gradient(top, #222222, #111111); - background-image: -o-linear-gradient(top, #222222, #111111); - background-image: linear-gradient(to bottom, #222222, #111111); - background-repeat: repeat-x; - border-color: #252525; - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222', endColorstr='#ff111111', GradientType=0); -} - -.navbar-inverse .brand, -.navbar-inverse .nav > li > a { - color: #999999; - text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); -} - -.navbar-inverse .brand:hover, -.navbar-inverse .nav > li > a:hover, -.navbar-inverse .brand:focus, -.navbar-inverse .nav > li > a:focus { - color: #ffffff; -} - -.navbar-inverse .brand { - color: #999999; -} - -.navbar-inverse .navbar-text { - color: #999999; -} - -.navbar-inverse .nav > li > a:focus, -.navbar-inverse .nav > li > a:hover { - color: #ffffff; - background-color: transparent; -} - -.navbar-inverse .nav .active > a, -.navbar-inverse .nav .active > a:hover, -.navbar-inverse .nav .active > a:focus { - color: #ffffff; - background-color: #111111; -} - -.navbar-inverse .navbar-link { - color: #999999; -} - -.navbar-inverse .navbar-link:hover, -.navbar-inverse .navbar-link:focus { - color: #ffffff; -} - -.navbar-inverse .divider-vertical { - border-right-color: #222222; - border-left-color: #111111; -} - -.navbar-inverse .nav li.dropdown.open > .dropdown-toggle, -.navbar-inverse .nav li.dropdown.active > .dropdown-toggle, -.navbar-inverse .nav li.dropdown.open.active > .dropdown-toggle { - color: #ffffff; - background-color: #111111; -} - -.navbar-inverse .nav li.dropdown > a:hover .caret, -.navbar-inverse .nav li.dropdown > a:focus .caret { - border-top-color: #ffffff; - border-bottom-color: #ffffff; -} - -.navbar-inverse .nav li.dropdown > .dropdown-toggle .caret { - border-top-color: #999999; - border-bottom-color: #999999; -} - -.navbar-inverse .nav li.dropdown.open > .dropdown-toggle .caret, -.navbar-inverse .nav li.dropdown.active > .dropdown-toggle .caret, -.navbar-inverse .nav li.dropdown.open.active > .dropdown-toggle .caret { - border-top-color: #ffffff; - border-bottom-color: #ffffff; -} - -.navbar-inverse .navbar-search .search-query { - color: #ffffff; - background-color: #515151; - border-color: #111111; - -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15); - -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15); - box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15); - -webkit-transition: none; - -moz-transition: none; - -o-transition: none; - transition: none; -} - -.navbar-inverse .navbar-search .search-query:-moz-placeholder { - color: #cccccc; -} - -.navbar-inverse .navbar-search .search-query:-ms-input-placeholder { - color: #cccccc; -} - -.navbar-inverse .navbar-search .search-query::-webkit-input-placeholder { - color: #cccccc; -} - -.navbar-inverse .navbar-search .search-query:focus, -.navbar-inverse .navbar-search .search-query.focused { - padding: 5px 15px; - color: #333333; - text-shadow: 0 1px 0 #ffffff; - background-color: #ffffff; - border: 0; - outline: 0; - -webkit-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15); - -moz-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15); - box-shadow: 0 0 3px rgba(0, 0, 0, 0.15); -} - -.navbar-inverse .btn-navbar { - color: #ffffff; - text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); - background-color: #0e0e0e; - *background-color: #040404; - background-image: -moz-linear-gradient(top, #151515, #040404); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#151515), to(#040404)); - background-image: -webkit-linear-gradient(top, #151515, #040404); - background-image: -o-linear-gradient(top, #151515, #040404); - background-image: linear-gradient(to bottom, #151515, #040404); - background-repeat: repeat-x; - border-color: #040404 #040404 #000000; - border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff151515', endColorstr='#ff040404', GradientType=0); - filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); -} - -.navbar-inverse .btn-navbar:hover, -.navbar-inverse .btn-navbar:focus, -.navbar-inverse .btn-navbar:active, -.navbar-inverse .btn-navbar.active, -.navbar-inverse .btn-navbar.disabled, -.navbar-inverse .btn-navbar[disabled] { - color: #ffffff; - background-color: #040404; - *background-color: #000000; -} - -.navbar-inverse .btn-navbar:active, -.navbar-inverse .btn-navbar.active { - background-color: #000000 \9; -} - -.breadcrumb { - padding: 8px 15px; - margin: 0 0 20px; - list-style: none; - background-color: #f5f5f5; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; -} - -.breadcrumb > li { - display: inline-block; - *display: inline; - text-shadow: 0 1px 0 #ffffff; - *zoom: 1; -} - -.breadcrumb > li > .divider { - padding: 0 5px; - color: #ccc; -} - -.breadcrumb > .active { - color: #999999; -} - -.pagination { - margin: 20px 0; -} - -.pagination ul { - display: inline-block; - *display: inline; - margin-bottom: 0; - margin-left: 0; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; - *zoom: 1; - -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); - -moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); - box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); -} - -.pagination ul > li { - display: inline; -} - -.pagination ul > li > a, -.pagination ul > li > span { - float: left; - padding: 4px 12px; - line-height: 20px; - text-decoration: none; - background-color: #ffffff; - border: 1px solid #dddddd; - border-left-width: 0; -} - -.pagination ul > li > a:hover, -.pagination ul > li > a:focus, -.pagination ul > .active > a, -.pagination ul > .active > span { - background-color: #f5f5f5; -} - -.pagination ul > .active > a, -.pagination ul > .active > span { - color: #999999; - cursor: default; -} - -.pagination ul > .disabled > span, -.pagination ul > .disabled > a, -.pagination ul > .disabled > a:hover, -.pagination ul > .disabled > a:focus { - color: #999999; - cursor: default; - background-color: transparent; -} - -.pagination ul > li:first-child > a, -.pagination ul > li:first-child > span { - border-left-width: 1px; - -webkit-border-bottom-left-radius: 4px; - border-bottom-left-radius: 4px; - -webkit-border-top-left-radius: 4px; - border-top-left-radius: 4px; - -moz-border-radius-bottomleft: 4px; - -moz-border-radius-topleft: 4px; -} - -.pagination ul > li:last-child > a, -.pagination ul > li:last-child > span { - -webkit-border-top-right-radius: 4px; - border-top-right-radius: 4px; - -webkit-border-bottom-right-radius: 4px; - border-bottom-right-radius: 4px; - -moz-border-radius-topright: 4px; - -moz-border-radius-bottomright: 4px; -} - -.pagination-centered { - text-align: center; -} - -.pagination-right { - text-align: right; -} - -.pagination-large ul > li > a, -.pagination-large ul > li > span { - padding: 11px 19px; - font-size: 17.5px; -} - -.pagination-large ul > li:first-child > a, -.pagination-large ul > li:first-child > span { - -webkit-border-bottom-left-radius: 6px; - border-bottom-left-radius: 6px; - -webkit-border-top-left-radius: 6px; - border-top-left-radius: 6px; - -moz-border-radius-bottomleft: 6px; - -moz-border-radius-topleft: 6px; -} - -.pagination-large ul > li:last-child > a, -.pagination-large ul > li:last-child > span { - -webkit-border-top-right-radius: 6px; - border-top-right-radius: 6px; - -webkit-border-bottom-right-radius: 6px; - border-bottom-right-radius: 6px; - -moz-border-radius-topright: 6px; - -moz-border-radius-bottomright: 6px; -} - -.pagination-mini ul > li:first-child > a, -.pagination-small ul > li:first-child > a, -.pagination-mini ul > li:first-child > span, -.pagination-small ul > li:first-child > span { - -webkit-border-bottom-left-radius: 3px; - border-bottom-left-radius: 3px; - -webkit-border-top-left-radius: 3px; - border-top-left-radius: 3px; - -moz-border-radius-bottomleft: 3px; - -moz-border-radius-topleft: 3px; -} - -.pagination-mini ul > li:last-child > a, -.pagination-small ul > li:last-child > a, -.pagination-mini ul > li:last-child > span, -.pagination-small ul > li:last-child > span { - -webkit-border-top-right-radius: 3px; - border-top-right-radius: 3px; - -webkit-border-bottom-right-radius: 3px; - border-bottom-right-radius: 3px; - -moz-border-radius-topright: 3px; - -moz-border-radius-bottomright: 3px; -} - -.pagination-small ul > li > a, -.pagination-small ul > li > span { - padding: 2px 10px; - font-size: 11.9px; -} - -.pagination-mini ul > li > a, -.pagination-mini ul > li > span { - padding: 0 6px; - font-size: 10.5px; -} - -.pager { - margin: 20px 0; - text-align: center; - list-style: none; - *zoom: 1; -} - -.pager:before, -.pager:after { - display: table; - line-height: 0; - content: ""; -} - -.pager:after { - clear: both; -} - -.pager li { - display: inline; -} - -.pager li > a, -.pager li > span { - display: inline-block; - padding: 5px 14px; - background-color: #fff; - border: 1px solid #ddd; - -webkit-border-radius: 15px; - -moz-border-radius: 15px; - border-radius: 15px; -} - -.pager li > a:hover, -.pager li > a:focus { - text-decoration: none; - background-color: #f5f5f5; -} - -.pager .next > a, -.pager .next > span { - float: right; -} - -.pager .previous > a, -.pager .previous > span { - float: left; -} - -.pager .disabled > a, -.pager .disabled > a:hover, -.pager .disabled > a:focus, -.pager .disabled > span { - color: #999999; - cursor: default; - background-color: #fff; -} - -.modal-backdrop { - position: fixed; - top: 0; - right: 0; - bottom: 0; - left: 0; - z-index: 1040; - background-color: #000000; -} - -.modal-backdrop.fade { - opacity: 0; -} - -.modal-backdrop, -.modal-backdrop.fade.in { - opacity: 0.8; - filter: alpha(opacity=80); -} - -.modal { - position: fixed; - top: 10%; - left: 50%; - z-index: 1050; - width: 560px; - margin-left: -280px; - background-color: #ffffff; - border: 1px solid #999; - border: 1px solid rgba(0, 0, 0, 0.3); - *border: 1px solid #999; - -webkit-border-radius: 6px; - -moz-border-radius: 6px; - border-radius: 6px; - outline: none; - -webkit-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); - -moz-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); - box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); - -webkit-background-clip: padding-box; - -moz-background-clip: padding-box; - background-clip: padding-box; -} - -.modal.fade { - top: -25%; - -webkit-transition: opacity 0.3s linear, top 0.3s ease-out; - -moz-transition: opacity 0.3s linear, top 0.3s ease-out; - -o-transition: opacity 0.3s linear, top 0.3s ease-out; - transition: opacity 0.3s linear, top 0.3s ease-out; -} - -.modal.fade.in { - top: 10%; -} - -.modal-header { - padding: 9px 15px; - border-bottom: 1px solid #eee; -} - -.modal-header .close { - margin-top: 2px; -} - -.modal-header h3 { - margin: 0; - line-height: 30px; -} - -.modal-body { - position: relative; - max-height: 400px; - padding: 15px; - overflow-y: auto; -} - -.modal-form { - margin-bottom: 0; -} - -.modal-footer { - padding: 14px 15px 15px; - margin-bottom: 0; - text-align: right; - background-color: #f5f5f5; - border-top: 1px solid #ddd; - -webkit-border-radius: 0 0 6px 6px; - -moz-border-radius: 0 0 6px 6px; - border-radius: 0 0 6px 6px; - *zoom: 1; - -webkit-box-shadow: inset 0 1px 0 #ffffff; - -moz-box-shadow: inset 0 1px 0 #ffffff; - box-shadow: inset 0 1px 0 #ffffff; -} - -.modal-footer:before, -.modal-footer:after { - display: table; - line-height: 0; - content: ""; -} - -.modal-footer:after { - clear: both; -} - -.modal-footer .btn + .btn { - margin-bottom: 0; - margin-left: 5px; -} - -.modal-footer .btn-group .btn + .btn { - margin-left: -1px; -} - -.modal-footer .btn-block + .btn-block { - margin-left: 0; -} - -.tooltip { - position: absolute; - z-index: 1030; - display: block; - font-size: 11px; - line-height: 1.4; - opacity: 0; - filter: alpha(opacity=0); - visibility: visible; -} - -.tooltip.in { - opacity: 0.8; - filter: alpha(opacity=80); -} - -.tooltip.top { - padding: 5px 0; - margin-top: -3px; -} - -.tooltip.right { - padding: 0 5px; - margin-left: 3px; -} - -.tooltip.bottom { - padding: 5px 0; - margin-top: 3px; -} - -.tooltip.left { - padding: 0 5px; - margin-left: -3px; -} - -.tooltip-inner { - max-width: 200px; - padding: 8px; - color: #ffffff; - text-align: center; - text-decoration: none; - background-color: #000000; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; -} - -.tooltip-arrow { - position: absolute; - width: 0; - height: 0; - border-color: transparent; - border-style: solid; -} - -.tooltip.top .tooltip-arrow { - bottom: 0; - left: 50%; - margin-left: -5px; - border-top-color: #000000; - border-width: 5px 5px 0; -} - -.tooltip.right .tooltip-arrow { - top: 50%; - left: 0; - margin-top: -5px; - border-right-color: #000000; - border-width: 5px 5px 5px 0; -} - -.tooltip.left .tooltip-arrow { - top: 50%; - right: 0; - margin-top: -5px; - border-left-color: #000000; - border-width: 5px 0 5px 5px; -} - -.tooltip.bottom .tooltip-arrow { - top: 0; - left: 50%; - margin-left: -5px; - border-bottom-color: #000000; - border-width: 0 5px 5px; -} - -.popover { - position: absolute; - top: 0; - left: 0; - z-index: 1010; - display: none; - max-width: 276px; - padding: 1px; - text-align: left; - white-space: normal; - background-color: #ffffff; - border: 1px solid #ccc; - border: 1px solid rgba(0, 0, 0, 0.2); - -webkit-border-radius: 6px; - -moz-border-radius: 6px; - border-radius: 6px; - -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); - -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); - box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); - -webkit-background-clip: padding-box; - -moz-background-clip: padding; - background-clip: padding-box; -} - -.popover.top { - margin-top: -10px; -} - -.popover.right { - margin-left: 10px; -} - -.popover.bottom { - margin-top: 10px; -} - -.popover.left { - margin-left: -10px; -} - -.popover-title { - padding: 8px 14px; - margin: 0; - font-size: 14px; - font-weight: normal; - line-height: 18px; - background-color: #f7f7f7; - border-bottom: 1px solid #ebebeb; - -webkit-border-radius: 5px 5px 0 0; - -moz-border-radius: 5px 5px 0 0; - border-radius: 5px 5px 0 0; -} - -.popover-title:empty { - display: none; -} - -.popover-content { - padding: 9px 14px; -} - -.popover .arrow, -.popover .arrow:after { - position: absolute; - display: block; - width: 0; - height: 0; - border-color: transparent; - border-style: solid; -} - -.popover .arrow { - border-width: 11px; -} - -.popover .arrow:after { - border-width: 10px; - content: ""; -} - -.popover.top .arrow { - bottom: -11px; - left: 50%; - margin-left: -11px; - border-top-color: #999; - border-top-color: rgba(0, 0, 0, 0.25); - border-bottom-width: 0; -} - -.popover.top .arrow:after { - bottom: 1px; - margin-left: -10px; - border-top-color: #ffffff; - border-bottom-width: 0; -} - -.popover.right .arrow { - top: 50%; - left: -11px; - margin-top: -11px; - border-right-color: #999; - border-right-color: rgba(0, 0, 0, 0.25); - border-left-width: 0; -} - -.popover.right .arrow:after { - bottom: -10px; - left: 1px; - border-right-color: #ffffff; - border-left-width: 0; -} - -.popover.bottom .arrow { - top: -11px; - left: 50%; - margin-left: -11px; - border-bottom-color: #999; - border-bottom-color: rgba(0, 0, 0, 0.25); - border-top-width: 0; -} - -.popover.bottom .arrow:after { - top: 1px; - margin-left: -10px; - border-bottom-color: #ffffff; - border-top-width: 0; -} - -.popover.left .arrow { - top: 50%; - right: -11px; - margin-top: -11px; - border-left-color: #999; - border-left-color: rgba(0, 0, 0, 0.25); - border-right-width: 0; -} - -.popover.left .arrow:after { - right: 1px; - bottom: -10px; - border-left-color: #ffffff; - border-right-width: 0; -} - -.thumbnails { - margin-left: -20px; - list-style: none; - *zoom: 1; -} - -.thumbnails:before, -.thumbnails:after { - display: table; - line-height: 0; - content: ""; -} - -.thumbnails:after { - clear: both; -} - -.row-fluid .thumbnails { - margin-left: 0; -} - -.thumbnails > li { - float: left; - margin-bottom: 20px; - margin-left: 20px; -} - -.thumbnail { - display: block; - padding: 4px; - line-height: 20px; - border: 1px solid #ddd; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; - -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055); - -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055); - box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055); - -webkit-transition: all 0.2s ease-in-out; - -moz-transition: all 0.2s ease-in-out; - -o-transition: all 0.2s ease-in-out; - transition: all 0.2s ease-in-out; -} - -a.thumbnail:hover, -a.thumbnail:focus { - border-color: #0088cc; - -webkit-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25); - -moz-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25); - box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25); -} - -.thumbnail > img { - display: block; - max-width: 100%; - margin-right: auto; - margin-left: auto; -} - -.thumbnail .caption { - padding: 9px; - color: #555555; -} - -.media, -.media-body { - overflow: hidden; - *overflow: visible; - zoom: 1; -} - -.media, -.media .media { - margin-top: 15px; -} - -.media:first-child { - margin-top: 0; -} - -.media-object { - display: block; -} - -.media-heading { - margin: 0 0 5px; -} - -.media > .pull-left { - margin-right: 10px; -} - -.media > .pull-right { - margin-left: 10px; -} - -.media-list { - margin-left: 0; - list-style: none; -} - -.label, -.badge { - display: inline-block; - padding: 2px 4px; - font-size: 11.844px; - font-weight: bold; - line-height: 14px; - color: #ffffff; - text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); - white-space: nowrap; - vertical-align: baseline; - background-color: #999999; -} - -.label { - -webkit-border-radius: 3px; - -moz-border-radius: 3px; - border-radius: 3px; -} - -.badge { - padding-right: 9px; - padding-left: 9px; - -webkit-border-radius: 9px; - -moz-border-radius: 9px; - border-radius: 9px; -} - -.label:empty, -.badge:empty { - display: none; -} - -a.label:hover, -a.label:focus, -a.badge:hover, -a.badge:focus { - color: #ffffff; - text-decoration: none; - cursor: pointer; -} - -.label-important, -.badge-important { - background-color: #b94a48; -} - -.label-important[href], -.badge-important[href] { - background-color: #953b39; -} - -.label-warning, -.badge-warning { - background-color: #f89406; -} - -.label-warning[href], -.badge-warning[href] { - background-color: #c67605; -} - -.label-success, -.badge-success { - background-color: #468847; -} - -.label-success[href], -.badge-success[href] { - background-color: #356635; -} - -.label-info, -.badge-info { - background-color: #3a87ad; -} - -.label-info[href], -.badge-info[href] { - background-color: #2d6987; -} - -.label-inverse, -.badge-inverse { - background-color: #333333; -} - -.label-inverse[href], -.badge-inverse[href] { - background-color: #1a1a1a; -} - -.btn .label, -.btn .badge { - position: relative; - top: -1px; -} - -.btn-mini .label, -.btn-mini .badge { - top: 0; -} - -@-webkit-keyframes progress-bar-stripes { - from { - background-position: 40px 0; - } - to { - background-position: 0 0; - } -} - -@-moz-keyframes progress-bar-stripes { - from { - background-position: 40px 0; - } - to { - background-position: 0 0; - } -} - -@-ms-keyframes progress-bar-stripes { - from { - background-position: 40px 0; - } - to { - background-position: 0 0; - } -} - -@-o-keyframes progress-bar-stripes { - from { - background-position: 0 0; - } - to { - background-position: 40px 0; - } -} - -@keyframes progress-bar-stripes { - from { - background-position: 40px 0; - } - to { - background-position: 0 0; - } -} - -.progress { - height: 20px; - margin-bottom: 20px; - overflow: hidden; - background-color: #f7f7f7; - background-image: -moz-linear-gradient(top, #f5f5f5, #f9f9f9); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f5f5f5), to(#f9f9f9)); - background-image: -webkit-linear-gradient(top, #f5f5f5, #f9f9f9); - background-image: -o-linear-gradient(top, #f5f5f5, #f9f9f9); - background-image: linear-gradient(to bottom, #f5f5f5, #f9f9f9); - background-repeat: repeat-x; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#fff9f9f9', GradientType=0); - -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); - -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); - box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); -} - -.progress .bar { - float: left; - width: 0; - height: 100%; - font-size: 12px; - color: #ffffff; - text-align: center; - text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); - background-color: #0e90d2; - background-image: -moz-linear-gradient(top, #149bdf, #0480be); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#149bdf), to(#0480be)); - background-image: -webkit-linear-gradient(top, #149bdf, #0480be); - background-image: -o-linear-gradient(top, #149bdf, #0480be); - background-image: linear-gradient(to bottom, #149bdf, #0480be); - background-repeat: repeat-x; - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff149bdf', endColorstr='#ff0480be', GradientType=0); - -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); - -moz-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); - box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; - -webkit-transition: width 0.6s ease; - -moz-transition: width 0.6s ease; - -o-transition: width 0.6s ease; - transition: width 0.6s ease; -} - -.progress .bar + .bar { - -webkit-box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15); - -moz-box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15); - box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15); -} - -.progress-striped .bar { - background-color: #149bdf; - background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); - background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - -webkit-background-size: 40px 40px; - -moz-background-size: 40px 40px; - -o-background-size: 40px 40px; - background-size: 40px 40px; -} - -.progress.active .bar { - -webkit-animation: progress-bar-stripes 2s linear infinite; - -moz-animation: progress-bar-stripes 2s linear infinite; - -ms-animation: progress-bar-stripes 2s linear infinite; - -o-animation: progress-bar-stripes 2s linear infinite; - animation: progress-bar-stripes 2s linear infinite; -} - -.progress-danger .bar, -.progress .bar-danger { - background-color: #dd514c; - background-image: -moz-linear-gradient(top, #ee5f5b, #c43c35); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#c43c35)); - background-image: -webkit-linear-gradient(top, #ee5f5b, #c43c35); - background-image: -o-linear-gradient(top, #ee5f5b, #c43c35); - background-image: linear-gradient(to bottom, #ee5f5b, #c43c35); - background-repeat: repeat-x; - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffc43c35', GradientType=0); -} - -.progress-danger.progress-striped .bar, -.progress-striped .bar-danger { - background-color: #ee5f5b; - background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); - background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); -} - -.progress-success .bar, -.progress .bar-success { - background-color: #5eb95e; - background-image: -moz-linear-gradient(top, #62c462, #57a957); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#57a957)); - background-image: -webkit-linear-gradient(top, #62c462, #57a957); - background-image: -o-linear-gradient(top, #62c462, #57a957); - background-image: linear-gradient(to bottom, #62c462, #57a957); - background-repeat: repeat-x; - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff57a957', GradientType=0); -} - -.progress-success.progress-striped .bar, -.progress-striped .bar-success { - background-color: #62c462; - background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); - background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); -} - -.progress-info .bar, -.progress .bar-info { - background-color: #4bb1cf; - background-image: -moz-linear-gradient(top, #5bc0de, #339bb9); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#339bb9)); - background-image: -webkit-linear-gradient(top, #5bc0de, #339bb9); - background-image: -o-linear-gradient(top, #5bc0de, #339bb9); - background-image: linear-gradient(to bottom, #5bc0de, #339bb9); - background-repeat: repeat-x; - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff339bb9', GradientType=0); -} - -.progress-info.progress-striped .bar, -.progress-striped .bar-info { - background-color: #5bc0de; - background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); - background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); -} - -.progress-warning .bar, -.progress .bar-warning { - background-color: #faa732; - background-image: -moz-linear-gradient(top, #fbb450, #f89406); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406)); - background-image: -webkit-linear-gradient(top, #fbb450, #f89406); - background-image: -o-linear-gradient(top, #fbb450, #f89406); - background-image: linear-gradient(to bottom, #fbb450, #f89406); - background-repeat: repeat-x; - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0); -} - -.progress-warning.progress-striped .bar, -.progress-striped .bar-warning { - background-color: #fbb450; - background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); - background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); -} - -.accordion { - margin-bottom: 20px; -} - -.accordion-group { - margin-bottom: 2px; - border: 1px solid #e5e5e5; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; -} - -.accordion-heading { - border-bottom: 0; -} - -.accordion-heading .accordion-toggle { - display: block; - padding: 8px 15px; -} - -.accordion-toggle { - cursor: pointer; -} - -.accordion-inner { - padding: 9px 15px; - border-top: 1px solid #e5e5e5; -} - -.carousel { - position: relative; - margin-bottom: 20px; - line-height: 1; -} - -.carousel-inner { - position: relative; - width: 100%; - overflow: hidden; -} - -.carousel-inner > .item { - position: relative; - display: none; - -webkit-transition: 0.6s ease-in-out left; - -moz-transition: 0.6s ease-in-out left; - -o-transition: 0.6s ease-in-out left; - transition: 0.6s ease-in-out left; -} - -.carousel-inner > .item > img, -.carousel-inner > .item > a > img { - display: block; - line-height: 1; -} - -.carousel-inner > .active, -.carousel-inner > .next, -.carousel-inner > .prev { - display: block; -} - -.carousel-inner > .active { - left: 0; -} - -.carousel-inner > .next, -.carousel-inner > .prev { - position: absolute; - top: 0; - width: 100%; -} - -.carousel-inner > .next { - left: 100%; -} - -.carousel-inner > .prev { - left: -100%; -} - -.carousel-inner > .next.left, -.carousel-inner > .prev.right { - left: 0; -} - -.carousel-inner > .active.left { - left: -100%; -} - -.carousel-inner > .active.right { - left: 100%; -} - -.carousel-control { - position: absolute; - top: 40%; - left: 15px; - width: 40px; - height: 40px; - margin-top: -20px; - font-size: 60px; - font-weight: 100; - line-height: 30px; - color: #ffffff; - text-align: center; - background: #222222; - border: 3px solid #ffffff; - -webkit-border-radius: 23px; - -moz-border-radius: 23px; - border-radius: 23px; - opacity: 0.5; - filter: alpha(opacity=50); -} - -.carousel-control.right { - right: 15px; - left: auto; -} - -.carousel-control:hover, -.carousel-control:focus { - color: #ffffff; - text-decoration: none; - opacity: 0.9; - filter: alpha(opacity=90); -} - -.carousel-indicators { - position: absolute; - top: 15px; - right: 15px; - z-index: 5; - margin: 0; - list-style: none; -} - -.carousel-indicators li { - display: block; - float: left; - width: 10px; - height: 10px; - margin-left: 5px; - text-indent: -999px; - background-color: #ccc; - background-color: rgba(255, 255, 255, 0.25); - border-radius: 5px; -} - -.carousel-indicators .active { - background-color: #fff; -} - -.carousel-caption { - position: absolute; - right: 0; - bottom: 0; - left: 0; - padding: 15px; - background: #333333; - background: rgba(0, 0, 0, 0.75); -} - -.carousel-caption h4, -.carousel-caption p { - line-height: 20px; - color: #ffffff; -} - -.carousel-caption h4 { - margin: 0 0 5px; -} - -.carousel-caption p { - margin-bottom: 0; -} - -.hero-unit { - padding: 60px; - margin-bottom: 30px; - font-size: 18px; - font-weight: 200; - line-height: 30px; - color: inherit; - background-color: #eeeeee; - -webkit-border-radius: 6px; - -moz-border-radius: 6px; - border-radius: 6px; -} - -.hero-unit h1 { - margin-bottom: 0; - font-size: 60px; - line-height: 1; - letter-spacing: -1px; - color: inherit; -} - -.hero-unit li { - line-height: 30px; -} - -.pull-right { - float: right; -} - -.pull-left { - float: left; -} - -.hide { - display: none; -} - -.show { - display: block; -} - -.invisible { - visibility: hidden; -} - -.affix { - position: fixed; -} diff --git a/webroot/bootstrap/css/bootstrap.min.css b/webroot/bootstrap/css/bootstrap.min.css deleted file mode 100644 index c10c7f41..00000000 --- a/webroot/bootstrap/css/bootstrap.min.css +++ /dev/null @@ -1,9 +0,0 @@ -/*! - * Bootstrap v2.3.1 - * - * Copyright 2012 Twitter, Inc - * Licensed under the Apache License v2.0 - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Designed and built with all the love in the world @twitter by @mdo and @fat. - */.clearfix{*zoom:1}.clearfix:before,.clearfix:after{display:table;line-height:0;content:""}.clearfix:after{clear:both}.hide-text{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.input-block-level{display:block;width:100%;min-height:30px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}article,aside,details,figcaption,figure,footer,header,hgroup,nav,section{display:block}audio,canvas,video{display:inline-block;*display:inline;*zoom:1}audio:not([controls]){display:none}html{font-size:100%;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}a:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}a:hover,a:active{outline:0}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sup{top:-0.5em}sub{bottom:-0.25em}img{width:auto\9;height:auto;max-width:100%;vertical-align:middle;border:0;-ms-interpolation-mode:bicubic}#map_canvas img,.google-maps img{max-width:none}button,input,select,textarea{margin:0;font-size:100%;vertical-align:middle}button,input{*overflow:visible;line-height:normal}button::-moz-focus-inner,input::-moz-focus-inner{padding:0;border:0}button,html input[type="button"],input[type="reset"],input[type="submit"]{cursor:pointer;-webkit-appearance:button}label,select,button,input[type="button"],input[type="reset"],input[type="submit"],input[type="radio"],input[type="checkbox"]{cursor:pointer}input[type="search"]{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;-webkit-appearance:textfield}input[type="search"]::-webkit-search-decoration,input[type="search"]::-webkit-search-cancel-button{-webkit-appearance:none}textarea{overflow:auto;vertical-align:top}@media print{*{color:#000!important;text-shadow:none!important;background:transparent!important;box-shadow:none!important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href) ")"}abbr[title]:after{content:" (" attr(title) ")"}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100%!important}@page{margin:.5cm}p,h2,h3{orphans:3;widows:3}h2,h3{page-break-after:avoid}}body{margin:0;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;line-height:20px;color:#333;background-color:#fff}a{color:#08c;text-decoration:none}a:hover,a:focus{color:#005580;text-decoration:underline}.img-rounded{-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px}.img-polaroid{padding:4px;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.2);-webkit-box-shadow:0 1px 3px rgba(0,0,0,0.1);-moz-box-shadow:0 1px 3px rgba(0,0,0,0.1);box-shadow:0 1px 3px rgba(0,0,0,0.1)}.img-circle{-webkit-border-radius:500px;-moz-border-radius:500px;border-radius:500px}.row{margin-left:-20px;*zoom:1}.row:before,.row:after{display:table;line-height:0;content:""}.row:after{clear:both}[class*="span"]{float:left;min-height:1px;margin-left:20px}.container,.navbar-static-top .container,.navbar-fixed-top .container,.navbar-fixed-bottom .container{width:940px}.span12{width:940px}.span11{width:860px}.span10{width:780px}.span9{width:700px}.span8{width:620px}.span7{width:540px}.span6{width:460px}.span5{width:380px}.span4{width:300px}.span3{width:220px}.span2{width:140px}.span1{width:60px}.offset12{margin-left:980px}.offset11{margin-left:900px}.offset10{margin-left:820px}.offset9{margin-left:740px}.offset8{margin-left:660px}.offset7{margin-left:580px}.offset6{margin-left:500px}.offset5{margin-left:420px}.offset4{margin-left:340px}.offset3{margin-left:260px}.offset2{margin-left:180px}.offset1{margin-left:100px}.row-fluid{width:100%;*zoom:1}.row-fluid:before,.row-fluid:after{display:table;line-height:0;content:""}.row-fluid:after{clear:both}.row-fluid [class*="span"]{display:block;float:left;width:100%;min-height:30px;margin-left:2.127659574468085%;*margin-left:2.074468085106383%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.row-fluid [class*="span"]:first-child{margin-left:0}.row-fluid .controls-row [class*="span"]+[class*="span"]{margin-left:2.127659574468085%}.row-fluid .span12{width:100%;*width:99.94680851063829%}.row-fluid .span11{width:91.48936170212765%;*width:91.43617021276594%}.row-fluid .span10{width:82.97872340425532%;*width:82.92553191489361%}.row-fluid .span9{width:74.46808510638297%;*width:74.41489361702126%}.row-fluid .span8{width:65.95744680851064%;*width:65.90425531914893%}.row-fluid .span7{width:57.44680851063829%;*width:57.39361702127659%}.row-fluid .span6{width:48.93617021276595%;*width:48.88297872340425%}.row-fluid .span5{width:40.42553191489362%;*width:40.37234042553192%}.row-fluid .span4{width:31.914893617021278%;*width:31.861702127659576%}.row-fluid .span3{width:23.404255319148934%;*width:23.351063829787233%}.row-fluid .span2{width:14.893617021276595%;*width:14.840425531914894%}.row-fluid .span1{width:6.382978723404255%;*width:6.329787234042553%}.row-fluid .offset12{margin-left:104.25531914893617%;*margin-left:104.14893617021275%}.row-fluid .offset12:first-child{margin-left:102.12765957446808%;*margin-left:102.02127659574467%}.row-fluid .offset11{margin-left:95.74468085106382%;*margin-left:95.6382978723404%}.row-fluid .offset11:first-child{margin-left:93.61702127659574%;*margin-left:93.51063829787232%}.row-fluid .offset10{margin-left:87.23404255319149%;*margin-left:87.12765957446807%}.row-fluid .offset10:first-child{margin-left:85.1063829787234%;*margin-left:84.99999999999999%}.row-fluid .offset9{margin-left:78.72340425531914%;*margin-left:78.61702127659572%}.row-fluid .offset9:first-child{margin-left:76.59574468085106%;*margin-left:76.48936170212764%}.row-fluid .offset8{margin-left:70.2127659574468%;*margin-left:70.10638297872339%}.row-fluid .offset8:first-child{margin-left:68.08510638297872%;*margin-left:67.9787234042553%}.row-fluid .offset7{margin-left:61.70212765957446%;*margin-left:61.59574468085106%}.row-fluid .offset7:first-child{margin-left:59.574468085106375%;*margin-left:59.46808510638297%}.row-fluid .offset6{margin-left:53.191489361702125%;*margin-left:53.085106382978715%}.row-fluid .offset6:first-child{margin-left:51.063829787234035%;*margin-left:50.95744680851063%}.row-fluid .offset5{margin-left:44.68085106382979%;*margin-left:44.57446808510638%}.row-fluid .offset5:first-child{margin-left:42.5531914893617%;*margin-left:42.4468085106383%}.row-fluid .offset4{margin-left:36.170212765957444%;*margin-left:36.06382978723405%}.row-fluid .offset4:first-child{margin-left:34.04255319148936%;*margin-left:33.93617021276596%}.row-fluid .offset3{margin-left:27.659574468085104%;*margin-left:27.5531914893617%}.row-fluid .offset3:first-child{margin-left:25.53191489361702%;*margin-left:25.425531914893618%}.row-fluid .offset2{margin-left:19.148936170212764%;*margin-left:19.04255319148936%}.row-fluid .offset2:first-child{margin-left:17.02127659574468%;*margin-left:16.914893617021278%}.row-fluid .offset1{margin-left:10.638297872340425%;*margin-left:10.53191489361702%}.row-fluid .offset1:first-child{margin-left:8.51063829787234%;*margin-left:8.404255319148938%}[class*="span"].hide,.row-fluid [class*="span"].hide{display:none}[class*="span"].pull-right,.row-fluid [class*="span"].pull-right{float:right}.container{margin-right:auto;margin-left:auto;*zoom:1}.container:before,.container:after{display:table;line-height:0;content:""}.container:after{clear:both}.container-fluid{padding-right:20px;padding-left:20px;*zoom:1}.container-fluid:before,.container-fluid:after{display:table;line-height:0;content:""}.container-fluid:after{clear:both}p{margin:0 0 10px}.lead{margin-bottom:20px;font-size:21px;font-weight:200;line-height:30px}small{font-size:85%}strong{font-weight:bold}em{font-style:italic}cite{font-style:normal}.muted{color:#999}a.muted:hover,a.muted:focus{color:#808080}.text-warning{color:#c09853}a.text-warning:hover,a.text-warning:focus{color:#a47e3c}.text-error{color:#b94a48}a.text-error:hover,a.text-error:focus{color:#953b39}.text-info{color:#3a87ad}a.text-info:hover,a.text-info:focus{color:#2d6987}.text-success{color:#468847}a.text-success:hover,a.text-success:focus{color:#356635}.text-left{text-align:left}.text-right{text-align:right}.text-center{text-align:center}h1,h2,h3,h4,h5,h6{margin:10px 0;font-family:inherit;font-weight:bold;line-height:20px;color:inherit;text-rendering:optimizelegibility}h1 small,h2 small,h3 small,h4 small,h5 small,h6 small{font-weight:normal;line-height:1;color:#999}h1,h2,h3{line-height:40px}h1{font-size:38.5px}h2{font-size:31.5px}h3{font-size:24.5px}h4{font-size:17.5px}h5{font-size:14px}h6{font-size:11.9px}h1 small{font-size:24.5px}h2 small{font-size:17.5px}h3 small{font-size:14px}h4 small{font-size:14px}.page-header{padding-bottom:9px;margin:20px 0 30px;border-bottom:1px solid #eee}ul,ol{padding:0;margin:0 0 10px 25px}ul ul,ul ol,ol ol,ol ul{margin-bottom:0}li{line-height:20px}ul.unstyled,ol.unstyled{margin-left:0;list-style:none}ul.inline,ol.inline{margin-left:0;list-style:none}ul.inline>li,ol.inline>li{display:inline-block;*display:inline;padding-right:5px;padding-left:5px;*zoom:1}dl{margin-bottom:20px}dt,dd{line-height:20px}dt{font-weight:bold}dd{margin-left:10px}.dl-horizontal{*zoom:1}.dl-horizontal:before,.dl-horizontal:after{display:table;line-height:0;content:""}.dl-horizontal:after{clear:both}.dl-horizontal dt{float:left;width:160px;overflow:hidden;clear:left;text-align:right;text-overflow:ellipsis;white-space:nowrap}.dl-horizontal dd{margin-left:180px}hr{margin:20px 0;border:0;border-top:1px solid #eee;border-bottom:1px solid #fff}abbr[title],abbr[data-original-title]{cursor:help;border-bottom:1px dotted #999}abbr.initialism{font-size:90%;text-transform:uppercase}blockquote{padding:0 0 0 15px;margin:0 0 20px;border-left:5px solid #eee}blockquote p{margin-bottom:0;font-size:17.5px;font-weight:300;line-height:1.25}blockquote small{display:block;line-height:20px;color:#999}blockquote small:before{content:'\2014 \00A0'}blockquote.pull-right{float:right;padding-right:15px;padding-left:0;border-right:5px solid #eee;border-left:0}blockquote.pull-right p,blockquote.pull-right small{text-align:right}blockquote.pull-right small:before{content:''}blockquote.pull-right small:after{content:'\00A0 \2014'}q:before,q:after,blockquote:before,blockquote:after{content:""}address{display:block;margin-bottom:20px;font-style:normal;line-height:20px}code,pre{padding:0 3px 2px;font-family:Monaco,Menlo,Consolas,"Courier New",monospace;font-size:12px;color:#333;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}code{padding:2px 4px;color:#d14;white-space:nowrap;background-color:#f7f7f9;border:1px solid #e1e1e8}pre{display:block;padding:9.5px;margin:0 0 10px;font-size:13px;line-height:20px;word-break:break-all;word-wrap:break-word;white-space:pre;white-space:pre-wrap;background-color:#f5f5f5;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.15);-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}pre.prettyprint{margin-bottom:20px}pre code{padding:0;color:inherit;white-space:pre;white-space:pre-wrap;background-color:transparent;border:0}.pre-scrollable{max-height:340px;overflow-y:scroll}form{margin:0 0 20px}fieldset{padding:0;margin:0;border:0}legend{display:block;width:100%;padding:0;margin-bottom:20px;font-size:21px;line-height:40px;color:#333;border:0;border-bottom:1px solid #e5e5e5}legend small{font-size:15px;color:#999}label,input,button,select,textarea{font-size:14px;font-weight:normal;line-height:20px}input,button,select,textarea{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif}label{display:block;margin-bottom:5px}select,textarea,input[type="text"],input[type="password"],input[type="datetime"],input[type="datetime-local"],input[type="date"],input[type="month"],input[type="time"],input[type="week"],input[type="number"],input[type="email"],input[type="url"],input[type="search"],input[type="tel"],input[type="color"],.uneditable-input{display:inline-block;height:20px;padding:4px 6px;margin-bottom:10px;font-size:14px;line-height:20px;color:#555;vertical-align:middle;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}input,textarea,.uneditable-input{width:206px}textarea{height:auto}textarea,input[type="text"],input[type="password"],input[type="datetime"],input[type="datetime-local"],input[type="date"],input[type="month"],input[type="time"],input[type="week"],input[type="number"],input[type="email"],input[type="url"],input[type="search"],input[type="tel"],input[type="color"],.uneditable-input{background-color:#fff;border:1px solid #ccc;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-webkit-transition:border linear .2s,box-shadow linear .2s;-moz-transition:border linear .2s,box-shadow linear .2s;-o-transition:border linear .2s,box-shadow linear .2s;transition:border linear .2s,box-shadow linear .2s}textarea:focus,input[type="text"]:focus,input[type="password"]:focus,input[type="datetime"]:focus,input[type="datetime-local"]:focus,input[type="date"]:focus,input[type="month"]:focus,input[type="time"]:focus,input[type="week"]:focus,input[type="number"]:focus,input[type="email"]:focus,input[type="url"]:focus,input[type="search"]:focus,input[type="tel"]:focus,input[type="color"]:focus,.uneditable-input:focus{border-color:rgba(82,168,236,0.8);outline:0;outline:thin dotted \9;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(82,168,236,0.6);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(82,168,236,0.6);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(82,168,236,0.6)}input[type="radio"],input[type="checkbox"]{margin:4px 0 0;margin-top:1px \9;*margin-top:0;line-height:normal}input[type="file"],input[type="image"],input[type="submit"],input[type="reset"],input[type="button"],input[type="radio"],input[type="checkbox"]{width:auto}select,input[type="file"]{height:30px;*margin-top:4px;line-height:30px}select{width:220px;background-color:#fff;border:1px solid #ccc}select[multiple],select[size]{height:auto}select:focus,input[type="file"]:focus,input[type="radio"]:focus,input[type="checkbox"]:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.uneditable-input,.uneditable-textarea{color:#999;cursor:not-allowed;background-color:#fcfcfc;border-color:#ccc;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.025);-moz-box-shadow:inset 0 1px 2px rgba(0,0,0,0.025);box-shadow:inset 0 1px 2px rgba(0,0,0,0.025)}.uneditable-input{overflow:hidden;white-space:nowrap}.uneditable-textarea{width:auto;height:auto}input:-moz-placeholder,textarea:-moz-placeholder{color:#999}input:-ms-input-placeholder,textarea:-ms-input-placeholder{color:#999}input::-webkit-input-placeholder,textarea::-webkit-input-placeholder{color:#999}.radio,.checkbox{min-height:20px;padding-left:20px}.radio input[type="radio"],.checkbox input[type="checkbox"]{float:left;margin-left:-20px}.controls>.radio:first-child,.controls>.checkbox:first-child{padding-top:5px}.radio.inline,.checkbox.inline{display:inline-block;padding-top:5px;margin-bottom:0;vertical-align:middle}.radio.inline+.radio.inline,.checkbox.inline+.checkbox.inline{margin-left:10px}.input-mini{width:60px}.input-small{width:90px}.input-medium{width:150px}.input-large{width:210px}.input-xlarge{width:270px}.input-xxlarge{width:530px}input[class*="span"],select[class*="span"],textarea[class*="span"],.uneditable-input[class*="span"],.row-fluid input[class*="span"],.row-fluid select[class*="span"],.row-fluid textarea[class*="span"],.row-fluid .uneditable-input[class*="span"]{float:none;margin-left:0}.input-append input[class*="span"],.input-append .uneditable-input[class*="span"],.input-prepend input[class*="span"],.input-prepend .uneditable-input[class*="span"],.row-fluid input[class*="span"],.row-fluid select[class*="span"],.row-fluid textarea[class*="span"],.row-fluid .uneditable-input[class*="span"],.row-fluid .input-prepend [class*="span"],.row-fluid .input-append [class*="span"]{display:inline-block}input,textarea,.uneditable-input{margin-left:0}.controls-row [class*="span"]+[class*="span"]{margin-left:20px}input.span12,textarea.span12,.uneditable-input.span12{width:926px}input.span11,textarea.span11,.uneditable-input.span11{width:846px}input.span10,textarea.span10,.uneditable-input.span10{width:766px}input.span9,textarea.span9,.uneditable-input.span9{width:686px}input.span8,textarea.span8,.uneditable-input.span8{width:606px}input.span7,textarea.span7,.uneditable-input.span7{width:526px}input.span6,textarea.span6,.uneditable-input.span6{width:446px}input.span5,textarea.span5,.uneditable-input.span5{width:366px}input.span4,textarea.span4,.uneditable-input.span4{width:286px}input.span3,textarea.span3,.uneditable-input.span3{width:206px}input.span2,textarea.span2,.uneditable-input.span2{width:126px}input.span1,textarea.span1,.uneditable-input.span1{width:46px}.controls-row{*zoom:1}.controls-row:before,.controls-row:after{display:table;line-height:0;content:""}.controls-row:after{clear:both}.controls-row [class*="span"],.row-fluid .controls-row [class*="span"]{float:left}.controls-row .checkbox[class*="span"],.controls-row .radio[class*="span"]{padding-top:5px}input[disabled],select[disabled],textarea[disabled],input[readonly],select[readonly],textarea[readonly]{cursor:not-allowed;background-color:#eee}input[type="radio"][disabled],input[type="checkbox"][disabled],input[type="radio"][readonly],input[type="checkbox"][readonly]{background-color:transparent}.control-group.warning .control-label,.control-group.warning .help-block,.control-group.warning .help-inline{color:#c09853}.control-group.warning .checkbox,.control-group.warning .radio,.control-group.warning input,.control-group.warning select,.control-group.warning textarea{color:#c09853}.control-group.warning input,.control-group.warning select,.control-group.warning textarea{border-color:#c09853;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.control-group.warning input:focus,.control-group.warning select:focus,.control-group.warning textarea:focus{border-color:#a47e3c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #dbc59e;-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #dbc59e;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #dbc59e}.control-group.warning .input-prepend .add-on,.control-group.warning .input-append .add-on{color:#c09853;background-color:#fcf8e3;border-color:#c09853}.control-group.error .control-label,.control-group.error .help-block,.control-group.error .help-inline{color:#b94a48}.control-group.error .checkbox,.control-group.error .radio,.control-group.error input,.control-group.error select,.control-group.error textarea{color:#b94a48}.control-group.error input,.control-group.error select,.control-group.error textarea{border-color:#b94a48;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.control-group.error input:focus,.control-group.error select:focus,.control-group.error textarea:focus{border-color:#953b39;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #d59392;-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #d59392;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #d59392}.control-group.error .input-prepend .add-on,.control-group.error .input-append .add-on{color:#b94a48;background-color:#f2dede;border-color:#b94a48}.control-group.success .control-label,.control-group.success .help-block,.control-group.success .help-inline{color:#468847}.control-group.success .checkbox,.control-group.success .radio,.control-group.success input,.control-group.success select,.control-group.success textarea{color:#468847}.control-group.success input,.control-group.success select,.control-group.success textarea{border-color:#468847;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.control-group.success input:focus,.control-group.success select:focus,.control-group.success textarea:focus{border-color:#356635;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7aba7b;-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7aba7b;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7aba7b}.control-group.success .input-prepend .add-on,.control-group.success .input-append .add-on{color:#468847;background-color:#dff0d8;border-color:#468847}.control-group.info .control-label,.control-group.info .help-block,.control-group.info .help-inline{color:#3a87ad}.control-group.info .checkbox,.control-group.info .radio,.control-group.info input,.control-group.info select,.control-group.info textarea{color:#3a87ad}.control-group.info input,.control-group.info select,.control-group.info textarea{border-color:#3a87ad;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.control-group.info input:focus,.control-group.info select:focus,.control-group.info textarea:focus{border-color:#2d6987;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7ab5d3;-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7ab5d3;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7ab5d3}.control-group.info .input-prepend .add-on,.control-group.info .input-append .add-on{color:#3a87ad;background-color:#d9edf7;border-color:#3a87ad}input:focus:invalid,textarea:focus:invalid,select:focus:invalid{color:#b94a48;border-color:#ee5f5b}input:focus:invalid:focus,textarea:focus:invalid:focus,select:focus:invalid:focus{border-color:#e9322d;-webkit-box-shadow:0 0 6px #f8b9b7;-moz-box-shadow:0 0 6px #f8b9b7;box-shadow:0 0 6px #f8b9b7}.form-actions{padding:19px 20px 20px;margin-top:20px;margin-bottom:20px;background-color:#f5f5f5;border-top:1px solid #e5e5e5;*zoom:1}.form-actions:before,.form-actions:after{display:table;line-height:0;content:""}.form-actions:after{clear:both}.help-block,.help-inline{color:#595959}.help-block{display:block;margin-bottom:10px}.help-inline{display:inline-block;*display:inline;padding-left:5px;vertical-align:middle;*zoom:1}.input-append,.input-prepend{display:inline-block;margin-bottom:10px;font-size:0;white-space:nowrap;vertical-align:middle}.input-append input,.input-prepend input,.input-append select,.input-prepend select,.input-append .uneditable-input,.input-prepend .uneditable-input,.input-append .dropdown-menu,.input-prepend .dropdown-menu,.input-append .popover,.input-prepend .popover{font-size:14px}.input-append input,.input-prepend input,.input-append select,.input-prepend select,.input-append .uneditable-input,.input-prepend .uneditable-input{position:relative;margin-bottom:0;*margin-left:0;vertical-align:top;-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0}.input-append input:focus,.input-prepend input:focus,.input-append select:focus,.input-prepend select:focus,.input-append .uneditable-input:focus,.input-prepend .uneditable-input:focus{z-index:2}.input-append .add-on,.input-prepend .add-on{display:inline-block;width:auto;height:20px;min-width:16px;padding:4px 5px;font-size:14px;font-weight:normal;line-height:20px;text-align:center;text-shadow:0 1px 0 #fff;background-color:#eee;border:1px solid #ccc}.input-append .add-on,.input-prepend .add-on,.input-append .btn,.input-prepend .btn,.input-append .btn-group>.dropdown-toggle,.input-prepend .btn-group>.dropdown-toggle{vertical-align:top;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.input-append .active,.input-prepend .active{background-color:#a9dba9;border-color:#46a546}.input-prepend .add-on,.input-prepend .btn{margin-right:-1px}.input-prepend .add-on:first-child,.input-prepend .btn:first-child{-webkit-border-radius:4px 0 0 4px;-moz-border-radius:4px 0 0 4px;border-radius:4px 0 0 4px}.input-append input,.input-append select,.input-append .uneditable-input{-webkit-border-radius:4px 0 0 4px;-moz-border-radius:4px 0 0 4px;border-radius:4px 0 0 4px}.input-append input+.btn-group .btn:last-child,.input-append select+.btn-group .btn:last-child,.input-append .uneditable-input+.btn-group .btn:last-child{-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0}.input-append .add-on,.input-append .btn,.input-append .btn-group{margin-left:-1px}.input-append .add-on:last-child,.input-append .btn:last-child,.input-append .btn-group:last-child>.dropdown-toggle{-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0}.input-prepend.input-append input,.input-prepend.input-append select,.input-prepend.input-append .uneditable-input{-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.input-prepend.input-append input+.btn-group .btn,.input-prepend.input-append select+.btn-group .btn,.input-prepend.input-append .uneditable-input+.btn-group .btn{-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0}.input-prepend.input-append .add-on:first-child,.input-prepend.input-append .btn:first-child{margin-right:-1px;-webkit-border-radius:4px 0 0 4px;-moz-border-radius:4px 0 0 4px;border-radius:4px 0 0 4px}.input-prepend.input-append .add-on:last-child,.input-prepend.input-append .btn:last-child{margin-left:-1px;-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0}.input-prepend.input-append .btn-group:first-child{margin-left:0}input.search-query{padding-right:14px;padding-right:4px \9;padding-left:14px;padding-left:4px \9;margin-bottom:0;-webkit-border-radius:15px;-moz-border-radius:15px;border-radius:15px}.form-search .input-append .search-query,.form-search .input-prepend .search-query{-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.form-search .input-append .search-query{-webkit-border-radius:14px 0 0 14px;-moz-border-radius:14px 0 0 14px;border-radius:14px 0 0 14px}.form-search .input-append .btn{-webkit-border-radius:0 14px 14px 0;-moz-border-radius:0 14px 14px 0;border-radius:0 14px 14px 0}.form-search .input-prepend .search-query{-webkit-border-radius:0 14px 14px 0;-moz-border-radius:0 14px 14px 0;border-radius:0 14px 14px 0}.form-search .input-prepend .btn{-webkit-border-radius:14px 0 0 14px;-moz-border-radius:14px 0 0 14px;border-radius:14px 0 0 14px}.form-search input,.form-inline input,.form-horizontal input,.form-search textarea,.form-inline textarea,.form-horizontal textarea,.form-search select,.form-inline select,.form-horizontal select,.form-search .help-inline,.form-inline .help-inline,.form-horizontal .help-inline,.form-search .uneditable-input,.form-inline .uneditable-input,.form-horizontal .uneditable-input,.form-search .input-prepend,.form-inline .input-prepend,.form-horizontal .input-prepend,.form-search .input-append,.form-inline .input-append,.form-horizontal .input-append{display:inline-block;*display:inline;margin-bottom:0;vertical-align:middle;*zoom:1}.form-search .hide,.form-inline .hide,.form-horizontal .hide{display:none}.form-search label,.form-inline label,.form-search .btn-group,.form-inline .btn-group{display:inline-block}.form-search .input-append,.form-inline .input-append,.form-search .input-prepend,.form-inline .input-prepend{margin-bottom:0}.form-search .radio,.form-search .checkbox,.form-inline .radio,.form-inline .checkbox{padding-left:0;margin-bottom:0;vertical-align:middle}.form-search .radio input[type="radio"],.form-search .checkbox input[type="checkbox"],.form-inline .radio input[type="radio"],.form-inline .checkbox input[type="checkbox"]{float:left;margin-right:3px;margin-left:0}.control-group{margin-bottom:10px}legend+.control-group{margin-top:20px;-webkit-margin-top-collapse:separate}.form-horizontal .control-group{margin-bottom:20px;*zoom:1}.form-horizontal .control-group:before,.form-horizontal .control-group:after{display:table;line-height:0;content:""}.form-horizontal .control-group:after{clear:both}.form-horizontal .control-label{float:left;width:160px;padding-top:5px;text-align:right}.form-horizontal .controls{*display:inline-block;*padding-left:20px;margin-left:180px;*margin-left:0}.form-horizontal .controls:first-child{*padding-left:180px}.form-horizontal .help-block{margin-bottom:0}.form-horizontal input+.help-block,.form-horizontal select+.help-block,.form-horizontal textarea+.help-block,.form-horizontal .uneditable-input+.help-block,.form-horizontal .input-prepend+.help-block,.form-horizontal .input-append+.help-block{margin-top:10px}.form-horizontal .form-actions{padding-left:180px}table{max-width:100%;background-color:transparent;border-collapse:collapse;border-spacing:0}.table{width:100%;margin-bottom:20px}.table th,.table td{padding:8px;line-height:20px;text-align:left;vertical-align:top;border-top:1px solid #ddd}.table th{font-weight:bold}.table thead th{vertical-align:bottom}.table caption+thead tr:first-child th,.table caption+thead tr:first-child td,.table colgroup+thead tr:first-child th,.table colgroup+thead tr:first-child td,.table thead:first-child tr:first-child th,.table thead:first-child tr:first-child td{border-top:0}.table tbody+tbody{border-top:2px solid #ddd}.table .table{background-color:#fff}.table-condensed th,.table-condensed td{padding:4px 5px}.table-bordered{border:1px solid #ddd;border-collapse:separate;*border-collapse:collapse;border-left:0;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.table-bordered th,.table-bordered td{border-left:1px solid #ddd}.table-bordered caption+thead tr:first-child th,.table-bordered caption+tbody tr:first-child th,.table-bordered caption+tbody tr:first-child td,.table-bordered colgroup+thead tr:first-child th,.table-bordered colgroup+tbody tr:first-child th,.table-bordered colgroup+tbody tr:first-child td,.table-bordered thead:first-child tr:first-child th,.table-bordered tbody:first-child tr:first-child th,.table-bordered tbody:first-child tr:first-child td{border-top:0}.table-bordered thead:first-child tr:first-child>th:first-child,.table-bordered tbody:first-child tr:first-child>td:first-child,.table-bordered tbody:first-child tr:first-child>th:first-child{-webkit-border-top-left-radius:4px;border-top-left-radius:4px;-moz-border-radius-topleft:4px}.table-bordered thead:first-child tr:first-child>th:last-child,.table-bordered tbody:first-child tr:first-child>td:last-child,.table-bordered tbody:first-child tr:first-child>th:last-child{-webkit-border-top-right-radius:4px;border-top-right-radius:4px;-moz-border-radius-topright:4px}.table-bordered thead:last-child tr:last-child>th:first-child,.table-bordered tbody:last-child tr:last-child>td:first-child,.table-bordered tbody:last-child tr:last-child>th:first-child,.table-bordered tfoot:last-child tr:last-child>td:first-child,.table-bordered tfoot:last-child tr:last-child>th:first-child{-webkit-border-bottom-left-radius:4px;border-bottom-left-radius:4px;-moz-border-radius-bottomleft:4px}.table-bordered thead:last-child tr:last-child>th:last-child,.table-bordered tbody:last-child tr:last-child>td:last-child,.table-bordered tbody:last-child tr:last-child>th:last-child,.table-bordered tfoot:last-child tr:last-child>td:last-child,.table-bordered tfoot:last-child tr:last-child>th:last-child{-webkit-border-bottom-right-radius:4px;border-bottom-right-radius:4px;-moz-border-radius-bottomright:4px}.table-bordered tfoot+tbody:last-child tr:last-child td:first-child{-webkit-border-bottom-left-radius:0;border-bottom-left-radius:0;-moz-border-radius-bottomleft:0}.table-bordered tfoot+tbody:last-child tr:last-child td:last-child{-webkit-border-bottom-right-radius:0;border-bottom-right-radius:0;-moz-border-radius-bottomright:0}.table-bordered caption+thead tr:first-child th:first-child,.table-bordered caption+tbody tr:first-child td:first-child,.table-bordered colgroup+thead tr:first-child th:first-child,.table-bordered colgroup+tbody tr:first-child td:first-child{-webkit-border-top-left-radius:4px;border-top-left-radius:4px;-moz-border-radius-topleft:4px}.table-bordered caption+thead tr:first-child th:last-child,.table-bordered caption+tbody tr:first-child td:last-child,.table-bordered colgroup+thead tr:first-child th:last-child,.table-bordered colgroup+tbody tr:first-child td:last-child{-webkit-border-top-right-radius:4px;border-top-right-radius:4px;-moz-border-radius-topright:4px}.table-striped tbody>tr:nth-child(odd)>td,.table-striped tbody>tr:nth-child(odd)>th{background-color:#f9f9f9}.table-hover tbody tr:hover>td,.table-hover tbody tr:hover>th{background-color:#f5f5f5}table td[class*="span"],table th[class*="span"],.row-fluid table td[class*="span"],.row-fluid table th[class*="span"]{display:table-cell;float:none;margin-left:0}.table td.span1,.table th.span1{float:none;width:44px;margin-left:0}.table td.span2,.table th.span2{float:none;width:124px;margin-left:0}.table td.span3,.table th.span3{float:none;width:204px;margin-left:0}.table td.span4,.table th.span4{float:none;width:284px;margin-left:0}.table td.span5,.table th.span5{float:none;width:364px;margin-left:0}.table td.span6,.table th.span6{float:none;width:444px;margin-left:0}.table td.span7,.table th.span7{float:none;width:524px;margin-left:0}.table td.span8,.table th.span8{float:none;width:604px;margin-left:0}.table td.span9,.table th.span9{float:none;width:684px;margin-left:0}.table td.span10,.table th.span10{float:none;width:764px;margin-left:0}.table td.span11,.table th.span11{float:none;width:844px;margin-left:0}.table td.span12,.table th.span12{float:none;width:924px;margin-left:0}.table tbody tr.success>td{background-color:#dff0d8}.table tbody tr.error>td{background-color:#f2dede}.table tbody tr.warning>td{background-color:#fcf8e3}.table tbody tr.info>td{background-color:#d9edf7}.table-hover tbody tr.success:hover>td{background-color:#d0e9c6}.table-hover tbody tr.error:hover>td{background-color:#ebcccc}.table-hover tbody tr.warning:hover>td{background-color:#faf2cc}.table-hover tbody tr.info:hover>td{background-color:#c4e3f3}[class^="icon-"],[class*=" icon-"]{display:inline-block;width:14px;height:14px;margin-top:1px;*margin-right:.3em;line-height:14px;vertical-align:text-top;background-image:url("../img/glyphicons-halflings.png");background-position:14px 14px;background-repeat:no-repeat}.icon-white,.nav-pills>.active>a>[class^="icon-"],.nav-pills>.active>a>[class*=" icon-"],.nav-list>.active>a>[class^="icon-"],.nav-list>.active>a>[class*=" icon-"],.navbar-inverse .nav>.active>a>[class^="icon-"],.navbar-inverse .nav>.active>a>[class*=" icon-"],.dropdown-menu>li>a:hover>[class^="icon-"],.dropdown-menu>li>a:focus>[class^="icon-"],.dropdown-menu>li>a:hover>[class*=" icon-"],.dropdown-menu>li>a:focus>[class*=" icon-"],.dropdown-menu>.active>a>[class^="icon-"],.dropdown-menu>.active>a>[class*=" icon-"],.dropdown-submenu:hover>a>[class^="icon-"],.dropdown-submenu:focus>a>[class^="icon-"],.dropdown-submenu:hover>a>[class*=" icon-"],.dropdown-submenu:focus>a>[class*=" icon-"]{background-image:url("../img/glyphicons-halflings-white.png")}.icon-glass{background-position:0 0}.icon-music{background-position:-24px 0}.icon-search{background-position:-48px 0}.icon-envelope{background-position:-72px 0}.icon-heart{background-position:-96px 0}.icon-star{background-position:-120px 0}.icon-star-empty{background-position:-144px 0}.icon-user{background-position:-168px 0}.icon-film{background-position:-192px 0}.icon-th-large{background-position:-216px 0}.icon-th{background-position:-240px 0}.icon-th-list{background-position:-264px 0}.icon-ok{background-position:-288px 0}.icon-remove{background-position:-312px 0}.icon-zoom-in{background-position:-336px 0}.icon-zoom-out{background-position:-360px 0}.icon-off{background-position:-384px 0}.icon-signal{background-position:-408px 0}.icon-cog{background-position:-432px 0}.icon-trash{background-position:-456px 0}.icon-home{background-position:0 -24px}.icon-file{background-position:-24px -24px}.icon-time{background-position:-48px -24px}.icon-road{background-position:-72px -24px}.icon-download-alt{background-position:-96px -24px}.icon-download{background-position:-120px -24px}.icon-upload{background-position:-144px -24px}.icon-inbox{background-position:-168px -24px}.icon-play-circle{background-position:-192px -24px}.icon-repeat{background-position:-216px -24px}.icon-refresh{background-position:-240px -24px}.icon-list-alt{background-position:-264px -24px}.icon-lock{background-position:-287px -24px}.icon-flag{background-position:-312px -24px}.icon-headphones{background-position:-336px -24px}.icon-volume-off{background-position:-360px -24px}.icon-volume-down{background-position:-384px -24px}.icon-volume-up{background-position:-408px -24px}.icon-qrcode{background-position:-432px -24px}.icon-barcode{background-position:-456px -24px}.icon-tag{background-position:0 -48px}.icon-tags{background-position:-25px -48px}.icon-book{background-position:-48px -48px}.icon-bookmark{background-position:-72px -48px}.icon-print{background-position:-96px -48px}.icon-camera{background-position:-120px -48px}.icon-font{background-position:-144px -48px}.icon-bold{background-position:-167px -48px}.icon-italic{background-position:-192px -48px}.icon-text-height{background-position:-216px -48px}.icon-text-width{background-position:-240px -48px}.icon-align-left{background-position:-264px -48px}.icon-align-center{background-position:-288px -48px}.icon-align-right{background-position:-312px -48px}.icon-align-justify{background-position:-336px -48px}.icon-list{background-position:-360px -48px}.icon-indent-left{background-position:-384px -48px}.icon-indent-right{background-position:-408px -48px}.icon-facetime-video{background-position:-432px -48px}.icon-picture{background-position:-456px -48px}.icon-pencil{background-position:0 -72px}.icon-map-marker{background-position:-24px -72px}.icon-adjust{background-position:-48px -72px}.icon-tint{background-position:-72px -72px}.icon-edit{background-position:-96px -72px}.icon-share{background-position:-120px -72px}.icon-check{background-position:-144px -72px}.icon-move{background-position:-168px -72px}.icon-step-backward{background-position:-192px -72px}.icon-fast-backward{background-position:-216px -72px}.icon-backward{background-position:-240px -72px}.icon-play{background-position:-264px -72px}.icon-pause{background-position:-288px -72px}.icon-stop{background-position:-312px -72px}.icon-forward{background-position:-336px -72px}.icon-fast-forward{background-position:-360px -72px}.icon-step-forward{background-position:-384px -72px}.icon-eject{background-position:-408px -72px}.icon-chevron-left{background-position:-432px -72px}.icon-chevron-right{background-position:-456px -72px}.icon-plus-sign{background-position:0 -96px}.icon-minus-sign{background-position:-24px -96px}.icon-remove-sign{background-position:-48px -96px}.icon-ok-sign{background-position:-72px -96px}.icon-question-sign{background-position:-96px -96px}.icon-info-sign{background-position:-120px -96px}.icon-screenshot{background-position:-144px -96px}.icon-remove-circle{background-position:-168px -96px}.icon-ok-circle{background-position:-192px -96px}.icon-ban-circle{background-position:-216px -96px}.icon-arrow-left{background-position:-240px -96px}.icon-arrow-right{background-position:-264px -96px}.icon-arrow-up{background-position:-289px -96px}.icon-arrow-down{background-position:-312px -96px}.icon-share-alt{background-position:-336px -96px}.icon-resize-full{background-position:-360px -96px}.icon-resize-small{background-position:-384px -96px}.icon-plus{background-position:-408px -96px}.icon-minus{background-position:-433px -96px}.icon-asterisk{background-position:-456px -96px}.icon-exclamation-sign{background-position:0 -120px}.icon-gift{background-position:-24px -120px}.icon-leaf{background-position:-48px -120px}.icon-fire{background-position:-72px -120px}.icon-eye-open{background-position:-96px -120px}.icon-eye-close{background-position:-120px -120px}.icon-warning-sign{background-position:-144px -120px}.icon-plane{background-position:-168px -120px}.icon-calendar{background-position:-192px -120px}.icon-random{width:16px;background-position:-216px -120px}.icon-comment{background-position:-240px -120px}.icon-magnet{background-position:-264px -120px}.icon-chevron-up{background-position:-288px -120px}.icon-chevron-down{background-position:-313px -119px}.icon-retweet{background-position:-336px -120px}.icon-shopping-cart{background-position:-360px -120px}.icon-folder-close{width:16px;background-position:-384px -120px}.icon-folder-open{width:16px;background-position:-408px -120px}.icon-resize-vertical{background-position:-432px -119px}.icon-resize-horizontal{background-position:-456px -118px}.icon-hdd{background-position:0 -144px}.icon-bullhorn{background-position:-24px -144px}.icon-bell{background-position:-48px -144px}.icon-certificate{background-position:-72px -144px}.icon-thumbs-up{background-position:-96px -144px}.icon-thumbs-down{background-position:-120px -144px}.icon-hand-right{background-position:-144px -144px}.icon-hand-left{background-position:-168px -144px}.icon-hand-up{background-position:-192px -144px}.icon-hand-down{background-position:-216px -144px}.icon-circle-arrow-right{background-position:-240px -144px}.icon-circle-arrow-left{background-position:-264px -144px}.icon-circle-arrow-up{background-position:-288px -144px}.icon-circle-arrow-down{background-position:-312px -144px}.icon-globe{background-position:-336px -144px}.icon-wrench{background-position:-360px -144px}.icon-tasks{background-position:-384px -144px}.icon-filter{background-position:-408px -144px}.icon-briefcase{background-position:-432px -144px}.icon-fullscreen{background-position:-456px -144px}.dropup,.dropdown{position:relative}.dropdown-toggle{*margin-bottom:-3px}.dropdown-toggle:active,.open .dropdown-toggle{outline:0}.caret{display:inline-block;width:0;height:0;vertical-align:top;border-top:4px solid #000;border-right:4px solid transparent;border-left:4px solid transparent;content:""}.dropdown .caret{margin-top:8px;margin-left:2px}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:160px;padding:5px 0;margin:2px 0 0;list-style:none;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.2);*border-right-width:2px;*border-bottom-width:2px;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,0.2);-moz-box-shadow:0 5px 10px rgba(0,0,0,0.2);box-shadow:0 5px 10px rgba(0,0,0,0.2);-webkit-background-clip:padding-box;-moz-background-clip:padding;background-clip:padding-box}.dropdown-menu.pull-right{right:0;left:auto}.dropdown-menu .divider{*width:100%;height:1px;margin:9px 1px;*margin:-5px 0 5px;overflow:hidden;background-color:#e5e5e5;border-bottom:1px solid #fff}.dropdown-menu>li>a{display:block;padding:3px 20px;clear:both;font-weight:normal;line-height:20px;color:#333;white-space:nowrap}.dropdown-menu>li>a:hover,.dropdown-menu>li>a:focus,.dropdown-submenu:hover>a,.dropdown-submenu:focus>a{color:#fff;text-decoration:none;background-color:#0081c2;background-image:-moz-linear-gradient(top,#08c,#0077b3);background-image:-webkit-gradient(linear,0 0,0 100%,from(#08c),to(#0077b3));background-image:-webkit-linear-gradient(top,#08c,#0077b3);background-image:-o-linear-gradient(top,#08c,#0077b3);background-image:linear-gradient(to bottom,#08c,#0077b3);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc',endColorstr='#ff0077b3',GradientType=0)}.dropdown-menu>.active>a,.dropdown-menu>.active>a:hover,.dropdown-menu>.active>a:focus{color:#fff;text-decoration:none;background-color:#0081c2;background-image:-moz-linear-gradient(top,#08c,#0077b3);background-image:-webkit-gradient(linear,0 0,0 100%,from(#08c),to(#0077b3));background-image:-webkit-linear-gradient(top,#08c,#0077b3);background-image:-o-linear-gradient(top,#08c,#0077b3);background-image:linear-gradient(to bottom,#08c,#0077b3);background-repeat:repeat-x;outline:0;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc',endColorstr='#ff0077b3',GradientType=0)}.dropdown-menu>.disabled>a,.dropdown-menu>.disabled>a:hover,.dropdown-menu>.disabled>a:focus{color:#999}.dropdown-menu>.disabled>a:hover,.dropdown-menu>.disabled>a:focus{text-decoration:none;cursor:default;background-color:transparent;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.open{*z-index:1000}.open>.dropdown-menu{display:block}.pull-right>.dropdown-menu{right:0;left:auto}.dropup .caret,.navbar-fixed-bottom .dropdown .caret{border-top:0;border-bottom:4px solid #000;content:""}.dropup .dropdown-menu,.navbar-fixed-bottom .dropdown .dropdown-menu{top:auto;bottom:100%;margin-bottom:1px}.dropdown-submenu{position:relative}.dropdown-submenu>.dropdown-menu{top:0;left:100%;margin-top:-6px;margin-left:-1px;-webkit-border-radius:0 6px 6px 6px;-moz-border-radius:0 6px 6px 6px;border-radius:0 6px 6px 6px}.dropdown-submenu:hover>.dropdown-menu{display:block}.dropup .dropdown-submenu>.dropdown-menu{top:auto;bottom:0;margin-top:0;margin-bottom:-2px;-webkit-border-radius:5px 5px 5px 0;-moz-border-radius:5px 5px 5px 0;border-radius:5px 5px 5px 0}.dropdown-submenu>a:after{display:block;float:right;width:0;height:0;margin-top:5px;margin-right:-10px;border-color:transparent;border-left-color:#ccc;border-style:solid;border-width:5px 0 5px 5px;content:" "}.dropdown-submenu:hover>a:after{border-left-color:#fff}.dropdown-submenu.pull-left{float:none}.dropdown-submenu.pull-left>.dropdown-menu{left:-100%;margin-left:10px;-webkit-border-radius:6px 0 6px 6px;-moz-border-radius:6px 0 6px 6px;border-radius:6px 0 6px 6px}.dropdown .dropdown-menu .nav-header{padding-right:20px;padding-left:20px}.typeahead{z-index:1051;margin-top:2px;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.well{min-height:20px;padding:19px;margin-bottom:20px;background-color:#f5f5f5;border:1px solid #e3e3e3;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.05);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.05);box-shadow:inset 0 1px 1px rgba(0,0,0,0.05)}.well blockquote{border-color:#ddd;border-color:rgba(0,0,0,0.15)}.well-large{padding:24px;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px}.well-small{padding:9px;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.fade{opacity:0;-webkit-transition:opacity .15s linear;-moz-transition:opacity .15s linear;-o-transition:opacity .15s linear;transition:opacity .15s linear}.fade.in{opacity:1}.collapse{position:relative;height:0;overflow:hidden;-webkit-transition:height .35s ease;-moz-transition:height .35s ease;-o-transition:height .35s ease;transition:height .35s ease}.collapse.in{height:auto}.close{float:right;font-size:20px;font-weight:bold;line-height:20px;color:#000;text-shadow:0 1px 0 #fff;opacity:.2;filter:alpha(opacity=20)}.close:hover,.close:focus{color:#000;text-decoration:none;cursor:pointer;opacity:.4;filter:alpha(opacity=40)}button.close{padding:0;cursor:pointer;background:transparent;border:0;-webkit-appearance:none}.btn{display:inline-block;*display:inline;padding:4px 12px;margin-bottom:0;*margin-left:.3em;font-size:14px;line-height:20px;color:#333;text-align:center;text-shadow:0 1px 1px rgba(255,255,255,0.75);vertical-align:middle;cursor:pointer;background-color:#f5f5f5;*background-color:#e6e6e6;background-image:-moz-linear-gradient(top,#fff,#e6e6e6);background-image:-webkit-gradient(linear,0 0,0 100%,from(#fff),to(#e6e6e6));background-image:-webkit-linear-gradient(top,#fff,#e6e6e6);background-image:-o-linear-gradient(top,#fff,#e6e6e6);background-image:linear-gradient(to bottom,#fff,#e6e6e6);background-repeat:repeat-x;border:1px solid #ccc;*border:0;border-color:#e6e6e6 #e6e6e6 #bfbfbf;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);border-bottom-color:#b3b3b3;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff',endColorstr='#ffe6e6e6',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);*zoom:1;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05);box-shadow:inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05)}.btn:hover,.btn:focus,.btn:active,.btn.active,.btn.disabled,.btn[disabled]{color:#333;background-color:#e6e6e6;*background-color:#d9d9d9}.btn:active,.btn.active{background-color:#ccc \9}.btn:first-child{*margin-left:0}.btn:hover,.btn:focus{color:#333;text-decoration:none;background-position:0 -15px;-webkit-transition:background-position .1s linear;-moz-transition:background-position .1s linear;-o-transition:background-position .1s linear;transition:background-position .1s linear}.btn:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.btn.active,.btn:active{background-image:none;outline:0;-webkit-box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05);box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05)}.btn.disabled,.btn[disabled]{cursor:default;background-image:none;opacity:.65;filter:alpha(opacity=65);-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none}.btn-large{padding:11px 19px;font-size:17.5px;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px}.btn-large [class^="icon-"],.btn-large [class*=" icon-"]{margin-top:4px}.btn-small{padding:2px 10px;font-size:11.9px;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.btn-small [class^="icon-"],.btn-small [class*=" icon-"]{margin-top:0}.btn-mini [class^="icon-"],.btn-mini [class*=" icon-"]{margin-top:-1px}.btn-mini{padding:0 6px;font-size:10.5px;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.btn-block{display:block;width:100%;padding-right:0;padding-left:0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.btn-block+.btn-block{margin-top:5px}input[type="submit"].btn-block,input[type="reset"].btn-block,input[type="button"].btn-block{width:100%}.btn-primary.active,.btn-warning.active,.btn-danger.active,.btn-success.active,.btn-info.active,.btn-inverse.active{color:rgba(255,255,255,0.75)}.btn-primary{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#006dcc;*background-color:#04c;background-image:-moz-linear-gradient(top,#08c,#04c);background-image:-webkit-gradient(linear,0 0,0 100%,from(#08c),to(#04c));background-image:-webkit-linear-gradient(top,#08c,#04c);background-image:-o-linear-gradient(top,#08c,#04c);background-image:linear-gradient(to bottom,#08c,#04c);background-repeat:repeat-x;border-color:#04c #04c #002a80;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc',endColorstr='#ff0044cc',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.btn-primary:hover,.btn-primary:focus,.btn-primary:active,.btn-primary.active,.btn-primary.disabled,.btn-primary[disabled]{color:#fff;background-color:#04c;*background-color:#003bb3}.btn-primary:active,.btn-primary.active{background-color:#039 \9}.btn-warning{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#faa732;*background-color:#f89406;background-image:-moz-linear-gradient(top,#fbb450,#f89406);background-image:-webkit-gradient(linear,0 0,0 100%,from(#fbb450),to(#f89406));background-image:-webkit-linear-gradient(top,#fbb450,#f89406);background-image:-o-linear-gradient(top,#fbb450,#f89406);background-image:linear-gradient(to bottom,#fbb450,#f89406);background-repeat:repeat-x;border-color:#f89406 #f89406 #ad6704;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450',endColorstr='#fff89406',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.btn-warning:hover,.btn-warning:focus,.btn-warning:active,.btn-warning.active,.btn-warning.disabled,.btn-warning[disabled]{color:#fff;background-color:#f89406;*background-color:#df8505}.btn-warning:active,.btn-warning.active{background-color:#c67605 \9}.btn-danger{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#da4f49;*background-color:#bd362f;background-image:-moz-linear-gradient(top,#ee5f5b,#bd362f);background-image:-webkit-gradient(linear,0 0,0 100%,from(#ee5f5b),to(#bd362f));background-image:-webkit-linear-gradient(top,#ee5f5b,#bd362f);background-image:-o-linear-gradient(top,#ee5f5b,#bd362f);background-image:linear-gradient(to bottom,#ee5f5b,#bd362f);background-repeat:repeat-x;border-color:#bd362f #bd362f #802420;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b',endColorstr='#ffbd362f',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.btn-danger:hover,.btn-danger:focus,.btn-danger:active,.btn-danger.active,.btn-danger.disabled,.btn-danger[disabled]{color:#fff;background-color:#bd362f;*background-color:#a9302a}.btn-danger:active,.btn-danger.active{background-color:#942a25 \9}.btn-success{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#5bb75b;*background-color:#51a351;background-image:-moz-linear-gradient(top,#62c462,#51a351);background-image:-webkit-gradient(linear,0 0,0 100%,from(#62c462),to(#51a351));background-image:-webkit-linear-gradient(top,#62c462,#51a351);background-image:-o-linear-gradient(top,#62c462,#51a351);background-image:linear-gradient(to bottom,#62c462,#51a351);background-repeat:repeat-x;border-color:#51a351 #51a351 #387038;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462',endColorstr='#ff51a351',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.btn-success:hover,.btn-success:focus,.btn-success:active,.btn-success.active,.btn-success.disabled,.btn-success[disabled]{color:#fff;background-color:#51a351;*background-color:#499249}.btn-success:active,.btn-success.active{background-color:#408140 \9}.btn-info{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#49afcd;*background-color:#2f96b4;background-image:-moz-linear-gradient(top,#5bc0de,#2f96b4);background-image:-webkit-gradient(linear,0 0,0 100%,from(#5bc0de),to(#2f96b4));background-image:-webkit-linear-gradient(top,#5bc0de,#2f96b4);background-image:-o-linear-gradient(top,#5bc0de,#2f96b4);background-image:linear-gradient(to bottom,#5bc0de,#2f96b4);background-repeat:repeat-x;border-color:#2f96b4 #2f96b4 #1f6377;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de',endColorstr='#ff2f96b4',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.btn-info:hover,.btn-info:focus,.btn-info:active,.btn-info.active,.btn-info.disabled,.btn-info[disabled]{color:#fff;background-color:#2f96b4;*background-color:#2a85a0}.btn-info:active,.btn-info.active{background-color:#24748c \9}.btn-inverse{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#363636;*background-color:#222;background-image:-moz-linear-gradient(top,#444,#222);background-image:-webkit-gradient(linear,0 0,0 100%,from(#444),to(#222));background-image:-webkit-linear-gradient(top,#444,#222);background-image:-o-linear-gradient(top,#444,#222);background-image:linear-gradient(to bottom,#444,#222);background-repeat:repeat-x;border-color:#222 #222 #000;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff444444',endColorstr='#ff222222',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.btn-inverse:hover,.btn-inverse:focus,.btn-inverse:active,.btn-inverse.active,.btn-inverse.disabled,.btn-inverse[disabled]{color:#fff;background-color:#222;*background-color:#151515}.btn-inverse:active,.btn-inverse.active{background-color:#080808 \9}button.btn,input[type="submit"].btn{*padding-top:3px;*padding-bottom:3px}button.btn::-moz-focus-inner,input[type="submit"].btn::-moz-focus-inner{padding:0;border:0}button.btn.btn-large,input[type="submit"].btn.btn-large{*padding-top:7px;*padding-bottom:7px}button.btn.btn-small,input[type="submit"].btn.btn-small{*padding-top:3px;*padding-bottom:3px}button.btn.btn-mini,input[type="submit"].btn.btn-mini{*padding-top:1px;*padding-bottom:1px}.btn-link,.btn-link:active,.btn-link[disabled]{background-color:transparent;background-image:none;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none}.btn-link{color:#08c;cursor:pointer;border-color:transparent;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.btn-link:hover,.btn-link:focus{color:#005580;text-decoration:underline;background-color:transparent}.btn-link[disabled]:hover,.btn-link[disabled]:focus{color:#333;text-decoration:none}.btn-group{position:relative;display:inline-block;*display:inline;*margin-left:.3em;font-size:0;white-space:nowrap;vertical-align:middle;*zoom:1}.btn-group:first-child{*margin-left:0}.btn-group+.btn-group{margin-left:5px}.btn-toolbar{margin-top:10px;margin-bottom:10px;font-size:0}.btn-toolbar>.btn+.btn,.btn-toolbar>.btn-group+.btn,.btn-toolbar>.btn+.btn-group{margin-left:5px}.btn-group>.btn{position:relative;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.btn-group>.btn+.btn{margin-left:-1px}.btn-group>.btn,.btn-group>.dropdown-menu,.btn-group>.popover{font-size:14px}.btn-group>.btn-mini{font-size:10.5px}.btn-group>.btn-small{font-size:11.9px}.btn-group>.btn-large{font-size:17.5px}.btn-group>.btn:first-child{margin-left:0;-webkit-border-bottom-left-radius:4px;border-bottom-left-radius:4px;-webkit-border-top-left-radius:4px;border-top-left-radius:4px;-moz-border-radius-bottomleft:4px;-moz-border-radius-topleft:4px}.btn-group>.btn:last-child,.btn-group>.dropdown-toggle{-webkit-border-top-right-radius:4px;border-top-right-radius:4px;-webkit-border-bottom-right-radius:4px;border-bottom-right-radius:4px;-moz-border-radius-topright:4px;-moz-border-radius-bottomright:4px}.btn-group>.btn.large:first-child{margin-left:0;-webkit-border-bottom-left-radius:6px;border-bottom-left-radius:6px;-webkit-border-top-left-radius:6px;border-top-left-radius:6px;-moz-border-radius-bottomleft:6px;-moz-border-radius-topleft:6px}.btn-group>.btn.large:last-child,.btn-group>.large.dropdown-toggle{-webkit-border-top-right-radius:6px;border-top-right-radius:6px;-webkit-border-bottom-right-radius:6px;border-bottom-right-radius:6px;-moz-border-radius-topright:6px;-moz-border-radius-bottomright:6px}.btn-group>.btn:hover,.btn-group>.btn:focus,.btn-group>.btn:active,.btn-group>.btn.active{z-index:2}.btn-group .dropdown-toggle:active,.btn-group.open .dropdown-toggle{outline:0}.btn-group>.btn+.dropdown-toggle{*padding-top:5px;padding-right:8px;*padding-bottom:5px;padding-left:8px;-webkit-box-shadow:inset 1px 0 0 rgba(255,255,255,0.125),inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:inset 1px 0 0 rgba(255,255,255,0.125),inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05);box-shadow:inset 1px 0 0 rgba(255,255,255,0.125),inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05)}.btn-group>.btn-mini+.dropdown-toggle{*padding-top:2px;padding-right:5px;*padding-bottom:2px;padding-left:5px}.btn-group>.btn-small+.dropdown-toggle{*padding-top:5px;*padding-bottom:4px}.btn-group>.btn-large+.dropdown-toggle{*padding-top:7px;padding-right:12px;*padding-bottom:7px;padding-left:12px}.btn-group.open .dropdown-toggle{background-image:none;-webkit-box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05);box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05)}.btn-group.open .btn.dropdown-toggle{background-color:#e6e6e6}.btn-group.open .btn-primary.dropdown-toggle{background-color:#04c}.btn-group.open .btn-warning.dropdown-toggle{background-color:#f89406}.btn-group.open .btn-danger.dropdown-toggle{background-color:#bd362f}.btn-group.open .btn-success.dropdown-toggle{background-color:#51a351}.btn-group.open .btn-info.dropdown-toggle{background-color:#2f96b4}.btn-group.open .btn-inverse.dropdown-toggle{background-color:#222}.btn .caret{margin-top:8px;margin-left:0}.btn-large .caret{margin-top:6px}.btn-large .caret{border-top-width:5px;border-right-width:5px;border-left-width:5px}.btn-mini .caret,.btn-small .caret{margin-top:8px}.dropup .btn-large .caret{border-bottom-width:5px}.btn-primary .caret,.btn-warning .caret,.btn-danger .caret,.btn-info .caret,.btn-success .caret,.btn-inverse .caret{border-top-color:#fff;border-bottom-color:#fff}.btn-group-vertical{display:inline-block;*display:inline;*zoom:1}.btn-group-vertical>.btn{display:block;float:none;max-width:100%;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.btn-group-vertical>.btn+.btn{margin-top:-1px;margin-left:0}.btn-group-vertical>.btn:first-child{-webkit-border-radius:4px 4px 0 0;-moz-border-radius:4px 4px 0 0;border-radius:4px 4px 0 0}.btn-group-vertical>.btn:last-child{-webkit-border-radius:0 0 4px 4px;-moz-border-radius:0 0 4px 4px;border-radius:0 0 4px 4px}.btn-group-vertical>.btn-large:first-child{-webkit-border-radius:6px 6px 0 0;-moz-border-radius:6px 6px 0 0;border-radius:6px 6px 0 0}.btn-group-vertical>.btn-large:last-child{-webkit-border-radius:0 0 6px 6px;-moz-border-radius:0 0 6px 6px;border-radius:0 0 6px 6px}.alert{padding:8px 35px 8px 14px;margin-bottom:20px;text-shadow:0 1px 0 rgba(255,255,255,0.5);background-color:#fcf8e3;border:1px solid #fbeed5;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.alert,.alert h4{color:#c09853}.alert h4{margin:0}.alert .close{position:relative;top:-2px;right:-21px;line-height:20px}.alert-success{color:#468847;background-color:#dff0d8;border-color:#d6e9c6}.alert-success h4{color:#468847}.alert-danger,.alert-error{color:#b94a48;background-color:#f2dede;border-color:#eed3d7}.alert-danger h4,.alert-error h4{color:#b94a48}.alert-info{color:#3a87ad;background-color:#d9edf7;border-color:#bce8f1}.alert-info h4{color:#3a87ad}.alert-block{padding-top:14px;padding-bottom:14px}.alert-block>p,.alert-block>ul{margin-bottom:0}.alert-block p+p{margin-top:5px}.nav{margin-bottom:20px;margin-left:0;list-style:none}.nav>li>a{display:block}.nav>li>a:hover,.nav>li>a:focus{text-decoration:none;background-color:#eee}.nav>li>a>img{max-width:none}.nav>.pull-right{float:right}.nav-header{display:block;padding:3px 15px;font-size:11px;font-weight:bold;line-height:20px;color:#999;text-shadow:0 1px 0 rgba(255,255,255,0.5);text-transform:uppercase}.nav li+.nav-header{margin-top:9px}.nav-list{padding-right:15px;padding-left:15px;margin-bottom:0}.nav-list>li>a,.nav-list .nav-header{margin-right:-15px;margin-left:-15px;text-shadow:0 1px 0 rgba(255,255,255,0.5)}.nav-list>li>a{padding:3px 15px}.nav-list>.active>a,.nav-list>.active>a:hover,.nav-list>.active>a:focus{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.2);background-color:#08c}.nav-list [class^="icon-"],.nav-list [class*=" icon-"]{margin-right:2px}.nav-list .divider{*width:100%;height:1px;margin:9px 1px;*margin:-5px 0 5px;overflow:hidden;background-color:#e5e5e5;border-bottom:1px solid #fff}.nav-tabs,.nav-pills{*zoom:1}.nav-tabs:before,.nav-pills:before,.nav-tabs:after,.nav-pills:after{display:table;line-height:0;content:""}.nav-tabs:after,.nav-pills:after{clear:both}.nav-tabs>li,.nav-pills>li{float:left}.nav-tabs>li>a,.nav-pills>li>a{padding-right:12px;padding-left:12px;margin-right:2px;line-height:14px}.nav-tabs{border-bottom:1px solid #ddd}.nav-tabs>li{margin-bottom:-1px}.nav-tabs>li>a{padding-top:8px;padding-bottom:8px;line-height:20px;border:1px solid transparent;-webkit-border-radius:4px 4px 0 0;-moz-border-radius:4px 4px 0 0;border-radius:4px 4px 0 0}.nav-tabs>li>a:hover,.nav-tabs>li>a:focus{border-color:#eee #eee #ddd}.nav-tabs>.active>a,.nav-tabs>.active>a:hover,.nav-tabs>.active>a:focus{color:#555;cursor:default;background-color:#fff;border:1px solid #ddd;border-bottom-color:transparent}.nav-pills>li>a{padding-top:8px;padding-bottom:8px;margin-top:2px;margin-bottom:2px;-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px}.nav-pills>.active>a,.nav-pills>.active>a:hover,.nav-pills>.active>a:focus{color:#fff;background-color:#08c}.nav-stacked>li{float:none}.nav-stacked>li>a{margin-right:0}.nav-tabs.nav-stacked{border-bottom:0}.nav-tabs.nav-stacked>li>a{border:1px solid #ddd;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.nav-tabs.nav-stacked>li:first-child>a{-webkit-border-top-right-radius:4px;border-top-right-radius:4px;-webkit-border-top-left-radius:4px;border-top-left-radius:4px;-moz-border-radius-topright:4px;-moz-border-radius-topleft:4px}.nav-tabs.nav-stacked>li:last-child>a{-webkit-border-bottom-right-radius:4px;border-bottom-right-radius:4px;-webkit-border-bottom-left-radius:4px;border-bottom-left-radius:4px;-moz-border-radius-bottomright:4px;-moz-border-radius-bottomleft:4px}.nav-tabs.nav-stacked>li>a:hover,.nav-tabs.nav-stacked>li>a:focus{z-index:2;border-color:#ddd}.nav-pills.nav-stacked>li>a{margin-bottom:3px}.nav-pills.nav-stacked>li:last-child>a{margin-bottom:1px}.nav-tabs .dropdown-menu{-webkit-border-radius:0 0 6px 6px;-moz-border-radius:0 0 6px 6px;border-radius:0 0 6px 6px}.nav-pills .dropdown-menu{-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px}.nav .dropdown-toggle .caret{margin-top:6px;border-top-color:#08c;border-bottom-color:#08c}.nav .dropdown-toggle:hover .caret,.nav .dropdown-toggle:focus .caret{border-top-color:#005580;border-bottom-color:#005580}.nav-tabs .dropdown-toggle .caret{margin-top:8px}.nav .active .dropdown-toggle .caret{border-top-color:#fff;border-bottom-color:#fff}.nav-tabs .active .dropdown-toggle .caret{border-top-color:#555;border-bottom-color:#555}.nav>.dropdown.active>a:hover,.nav>.dropdown.active>a:focus{cursor:pointer}.nav-tabs .open .dropdown-toggle,.nav-pills .open .dropdown-toggle,.nav>li.dropdown.open.active>a:hover,.nav>li.dropdown.open.active>a:focus{color:#fff;background-color:#999;border-color:#999}.nav li.dropdown.open .caret,.nav li.dropdown.open.active .caret,.nav li.dropdown.open a:hover .caret,.nav li.dropdown.open a:focus .caret{border-top-color:#fff;border-bottom-color:#fff;opacity:1;filter:alpha(opacity=100)}.tabs-stacked .open>a:hover,.tabs-stacked .open>a:focus{border-color:#999}.tabbable{*zoom:1}.tabbable:before,.tabbable:after{display:table;line-height:0;content:""}.tabbable:after{clear:both}.tab-content{overflow:auto}.tabs-below>.nav-tabs,.tabs-right>.nav-tabs,.tabs-left>.nav-tabs{border-bottom:0}.tab-content>.tab-pane,.pill-content>.pill-pane{display:none}.tab-content>.active,.pill-content>.active{display:block}.tabs-below>.nav-tabs{border-top:1px solid #ddd}.tabs-below>.nav-tabs>li{margin-top:-1px;margin-bottom:0}.tabs-below>.nav-tabs>li>a{-webkit-border-radius:0 0 4px 4px;-moz-border-radius:0 0 4px 4px;border-radius:0 0 4px 4px}.tabs-below>.nav-tabs>li>a:hover,.tabs-below>.nav-tabs>li>a:focus{border-top-color:#ddd;border-bottom-color:transparent}.tabs-below>.nav-tabs>.active>a,.tabs-below>.nav-tabs>.active>a:hover,.tabs-below>.nav-tabs>.active>a:focus{border-color:transparent #ddd #ddd #ddd}.tabs-left>.nav-tabs>li,.tabs-right>.nav-tabs>li{float:none}.tabs-left>.nav-tabs>li>a,.tabs-right>.nav-tabs>li>a{min-width:74px;margin-right:0;margin-bottom:3px}.tabs-left>.nav-tabs{float:left;margin-right:19px;border-right:1px solid #ddd}.tabs-left>.nav-tabs>li>a{margin-right:-1px;-webkit-border-radius:4px 0 0 4px;-moz-border-radius:4px 0 0 4px;border-radius:4px 0 0 4px}.tabs-left>.nav-tabs>li>a:hover,.tabs-left>.nav-tabs>li>a:focus{border-color:#eee #ddd #eee #eee}.tabs-left>.nav-tabs .active>a,.tabs-left>.nav-tabs .active>a:hover,.tabs-left>.nav-tabs .active>a:focus{border-color:#ddd transparent #ddd #ddd;*border-right-color:#fff}.tabs-right>.nav-tabs{float:right;margin-left:19px;border-left:1px solid #ddd}.tabs-right>.nav-tabs>li>a{margin-left:-1px;-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0}.tabs-right>.nav-tabs>li>a:hover,.tabs-right>.nav-tabs>li>a:focus{border-color:#eee #eee #eee #ddd}.tabs-right>.nav-tabs .active>a,.tabs-right>.nav-tabs .active>a:hover,.tabs-right>.nav-tabs .active>a:focus{border-color:#ddd #ddd #ddd transparent;*border-left-color:#fff}.nav>.disabled>a{color:#999}.nav>.disabled>a:hover,.nav>.disabled>a:focus{text-decoration:none;cursor:default;background-color:transparent}.navbar{*position:relative;*z-index:2;margin-bottom:20px;overflow:visible}.navbar-inner{min-height:40px;padding-right:20px;padding-left:20px;background-color:#fafafa;background-image:-moz-linear-gradient(top,#fff,#f2f2f2);background-image:-webkit-gradient(linear,0 0,0 100%,from(#fff),to(#f2f2f2));background-image:-webkit-linear-gradient(top,#fff,#f2f2f2);background-image:-o-linear-gradient(top,#fff,#f2f2f2);background-image:linear-gradient(to bottom,#fff,#f2f2f2);background-repeat:repeat-x;border:1px solid #d4d4d4;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff',endColorstr='#fff2f2f2',GradientType=0);*zoom:1;-webkit-box-shadow:0 1px 4px rgba(0,0,0,0.065);-moz-box-shadow:0 1px 4px rgba(0,0,0,0.065);box-shadow:0 1px 4px rgba(0,0,0,0.065)}.navbar-inner:before,.navbar-inner:after{display:table;line-height:0;content:""}.navbar-inner:after{clear:both}.navbar .container{width:auto}.nav-collapse.collapse{height:auto;overflow:visible}.navbar .brand{display:block;float:left;padding:10px 20px 10px;margin-left:-20px;font-size:20px;font-weight:200;color:#777;text-shadow:0 1px 0 #fff}.navbar .brand:hover,.navbar .brand:focus{text-decoration:none}.navbar-text{margin-bottom:0;line-height:40px;color:#777}.navbar-link{color:#777}.navbar-link:hover,.navbar-link:focus{color:#333}.navbar .divider-vertical{height:40px;margin:0 9px;border-right:1px solid #fff;border-left:1px solid #f2f2f2}.navbar .btn,.navbar .btn-group{margin-top:5px}.navbar .btn-group .btn,.navbar .input-prepend .btn,.navbar .input-append .btn,.navbar .input-prepend .btn-group,.navbar .input-append .btn-group{margin-top:0}.navbar-form{margin-bottom:0;*zoom:1}.navbar-form:before,.navbar-form:after{display:table;line-height:0;content:""}.navbar-form:after{clear:both}.navbar-form input,.navbar-form select,.navbar-form .radio,.navbar-form .checkbox{margin-top:5px}.navbar-form input,.navbar-form select,.navbar-form .btn{display:inline-block;margin-bottom:0}.navbar-form input[type="image"],.navbar-form input[type="checkbox"],.navbar-form input[type="radio"]{margin-top:3px}.navbar-form .input-append,.navbar-form .input-prepend{margin-top:5px;white-space:nowrap}.navbar-form .input-append input,.navbar-form .input-prepend input{margin-top:0}.navbar-search{position:relative;float:left;margin-top:5px;margin-bottom:0}.navbar-search .search-query{padding:4px 14px;margin-bottom:0;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:13px;font-weight:normal;line-height:1;-webkit-border-radius:15px;-moz-border-radius:15px;border-radius:15px}.navbar-static-top{position:static;margin-bottom:0}.navbar-static-top .navbar-inner{-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.navbar-fixed-top,.navbar-fixed-bottom{position:fixed;right:0;left:0;z-index:1030;margin-bottom:0}.navbar-fixed-top .navbar-inner,.navbar-static-top .navbar-inner{border-width:0 0 1px}.navbar-fixed-bottom .navbar-inner{border-width:1px 0 0}.navbar-fixed-top .navbar-inner,.navbar-fixed-bottom .navbar-inner{padding-right:0;padding-left:0;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.navbar-static-top .container,.navbar-fixed-top .container,.navbar-fixed-bottom .container{width:940px}.navbar-fixed-top{top:0}.navbar-fixed-top .navbar-inner,.navbar-static-top .navbar-inner{-webkit-box-shadow:0 1px 10px rgba(0,0,0,0.1);-moz-box-shadow:0 1px 10px rgba(0,0,0,0.1);box-shadow:0 1px 10px rgba(0,0,0,0.1)}.navbar-fixed-bottom{bottom:0}.navbar-fixed-bottom .navbar-inner{-webkit-box-shadow:0 -1px 10px rgba(0,0,0,0.1);-moz-box-shadow:0 -1px 10px rgba(0,0,0,0.1);box-shadow:0 -1px 10px rgba(0,0,0,0.1)}.navbar .nav{position:relative;left:0;display:block;float:left;margin:0 10px 0 0}.navbar .nav.pull-right{float:right;margin-right:0}.navbar .nav>li{float:left}.navbar .nav>li>a{float:none;padding:10px 15px 10px;color:#777;text-decoration:none;text-shadow:0 1px 0 #fff}.navbar .nav .dropdown-toggle .caret{margin-top:8px}.navbar .nav>li>a:focus,.navbar .nav>li>a:hover{color:#333;text-decoration:none;background-color:transparent}.navbar .nav>.active>a,.navbar .nav>.active>a:hover,.navbar .nav>.active>a:focus{color:#555;text-decoration:none;background-color:#e5e5e5;-webkit-box-shadow:inset 0 3px 8px rgba(0,0,0,0.125);-moz-box-shadow:inset 0 3px 8px rgba(0,0,0,0.125);box-shadow:inset 0 3px 8px rgba(0,0,0,0.125)}.navbar .btn-navbar{display:none;float:right;padding:7px 10px;margin-right:5px;margin-left:5px;color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#ededed;*background-color:#e5e5e5;background-image:-moz-linear-gradient(top,#f2f2f2,#e5e5e5);background-image:-webkit-gradient(linear,0 0,0 100%,from(#f2f2f2),to(#e5e5e5));background-image:-webkit-linear-gradient(top,#f2f2f2,#e5e5e5);background-image:-o-linear-gradient(top,#f2f2f2,#e5e5e5);background-image:linear-gradient(to bottom,#f2f2f2,#e5e5e5);background-repeat:repeat-x;border-color:#e5e5e5 #e5e5e5 #bfbfbf;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2f2f2',endColorstr='#ffe5e5e5',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.075);-moz-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.075);box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.075)}.navbar .btn-navbar:hover,.navbar .btn-navbar:focus,.navbar .btn-navbar:active,.navbar .btn-navbar.active,.navbar .btn-navbar.disabled,.navbar .btn-navbar[disabled]{color:#fff;background-color:#e5e5e5;*background-color:#d9d9d9}.navbar .btn-navbar:active,.navbar .btn-navbar.active{background-color:#ccc \9}.navbar .btn-navbar .icon-bar{display:block;width:18px;height:2px;background-color:#f5f5f5;-webkit-border-radius:1px;-moz-border-radius:1px;border-radius:1px;-webkit-box-shadow:0 1px 0 rgba(0,0,0,0.25);-moz-box-shadow:0 1px 0 rgba(0,0,0,0.25);box-shadow:0 1px 0 rgba(0,0,0,0.25)}.btn-navbar .icon-bar+.icon-bar{margin-top:3px}.navbar .nav>li>.dropdown-menu:before{position:absolute;top:-7px;left:9px;display:inline-block;border-right:7px solid transparent;border-bottom:7px solid #ccc;border-left:7px solid transparent;border-bottom-color:rgba(0,0,0,0.2);content:''}.navbar .nav>li>.dropdown-menu:after{position:absolute;top:-6px;left:10px;display:inline-block;border-right:6px solid transparent;border-bottom:6px solid #fff;border-left:6px solid transparent;content:''}.navbar-fixed-bottom .nav>li>.dropdown-menu:before{top:auto;bottom:-7px;border-top:7px solid #ccc;border-bottom:0;border-top-color:rgba(0,0,0,0.2)}.navbar-fixed-bottom .nav>li>.dropdown-menu:after{top:auto;bottom:-6px;border-top:6px solid #fff;border-bottom:0}.navbar .nav li.dropdown>a:hover .caret,.navbar .nav li.dropdown>a:focus .caret{border-top-color:#333;border-bottom-color:#333}.navbar .nav li.dropdown.open>.dropdown-toggle,.navbar .nav li.dropdown.active>.dropdown-toggle,.navbar .nav li.dropdown.open.active>.dropdown-toggle{color:#555;background-color:#e5e5e5}.navbar .nav li.dropdown>.dropdown-toggle .caret{border-top-color:#777;border-bottom-color:#777}.navbar .nav li.dropdown.open>.dropdown-toggle .caret,.navbar .nav li.dropdown.active>.dropdown-toggle .caret,.navbar .nav li.dropdown.open.active>.dropdown-toggle .caret{border-top-color:#555;border-bottom-color:#555}.navbar .pull-right>li>.dropdown-menu,.navbar .nav>li>.dropdown-menu.pull-right{right:0;left:auto}.navbar .pull-right>li>.dropdown-menu:before,.navbar .nav>li>.dropdown-menu.pull-right:before{right:12px;left:auto}.navbar .pull-right>li>.dropdown-menu:after,.navbar .nav>li>.dropdown-menu.pull-right:after{right:13px;left:auto}.navbar .pull-right>li>.dropdown-menu .dropdown-menu,.navbar .nav>li>.dropdown-menu.pull-right .dropdown-menu{right:100%;left:auto;margin-right:-1px;margin-left:0;-webkit-border-radius:6px 0 6px 6px;-moz-border-radius:6px 0 6px 6px;border-radius:6px 0 6px 6px}.navbar-inverse .navbar-inner{background-color:#1b1b1b;background-image:-moz-linear-gradient(top,#222,#111);background-image:-webkit-gradient(linear,0 0,0 100%,from(#222),to(#111));background-image:-webkit-linear-gradient(top,#222,#111);background-image:-o-linear-gradient(top,#222,#111);background-image:linear-gradient(to bottom,#222,#111);background-repeat:repeat-x;border-color:#252525;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222',endColorstr='#ff111111',GradientType=0)}.navbar-inverse .brand,.navbar-inverse .nav>li>a{color:#999;text-shadow:0 -1px 0 rgba(0,0,0,0.25)}.navbar-inverse .brand:hover,.navbar-inverse .nav>li>a:hover,.navbar-inverse .brand:focus,.navbar-inverse .nav>li>a:focus{color:#fff}.navbar-inverse .brand{color:#999}.navbar-inverse .navbar-text{color:#999}.navbar-inverse .nav>li>a:focus,.navbar-inverse .nav>li>a:hover{color:#fff;background-color:transparent}.navbar-inverse .nav .active>a,.navbar-inverse .nav .active>a:hover,.navbar-inverse .nav .active>a:focus{color:#fff;background-color:#111}.navbar-inverse .navbar-link{color:#999}.navbar-inverse .navbar-link:hover,.navbar-inverse .navbar-link:focus{color:#fff}.navbar-inverse .divider-vertical{border-right-color:#222;border-left-color:#111}.navbar-inverse .nav li.dropdown.open>.dropdown-toggle,.navbar-inverse .nav li.dropdown.active>.dropdown-toggle,.navbar-inverse .nav li.dropdown.open.active>.dropdown-toggle{color:#fff;background-color:#111}.navbar-inverse .nav li.dropdown>a:hover .caret,.navbar-inverse .nav li.dropdown>a:focus .caret{border-top-color:#fff;border-bottom-color:#fff}.navbar-inverse .nav li.dropdown>.dropdown-toggle .caret{border-top-color:#999;border-bottom-color:#999}.navbar-inverse .nav li.dropdown.open>.dropdown-toggle .caret,.navbar-inverse .nav li.dropdown.active>.dropdown-toggle .caret,.navbar-inverse .nav li.dropdown.open.active>.dropdown-toggle .caret{border-top-color:#fff;border-bottom-color:#fff}.navbar-inverse .navbar-search .search-query{color:#fff;background-color:#515151;border-color:#111;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.1),0 1px 0 rgba(255,255,255,0.15);-moz-box-shadow:inset 0 1px 2px rgba(0,0,0,0.1),0 1px 0 rgba(255,255,255,0.15);box-shadow:inset 0 1px 2px rgba(0,0,0,0.1),0 1px 0 rgba(255,255,255,0.15);-webkit-transition:none;-moz-transition:none;-o-transition:none;transition:none}.navbar-inverse .navbar-search .search-query:-moz-placeholder{color:#ccc}.navbar-inverse .navbar-search .search-query:-ms-input-placeholder{color:#ccc}.navbar-inverse .navbar-search .search-query::-webkit-input-placeholder{color:#ccc}.navbar-inverse .navbar-search .search-query:focus,.navbar-inverse .navbar-search .search-query.focused{padding:5px 15px;color:#333;text-shadow:0 1px 0 #fff;background-color:#fff;border:0;outline:0;-webkit-box-shadow:0 0 3px rgba(0,0,0,0.15);-moz-box-shadow:0 0 3px rgba(0,0,0,0.15);box-shadow:0 0 3px rgba(0,0,0,0.15)}.navbar-inverse .btn-navbar{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#0e0e0e;*background-color:#040404;background-image:-moz-linear-gradient(top,#151515,#040404);background-image:-webkit-gradient(linear,0 0,0 100%,from(#151515),to(#040404));background-image:-webkit-linear-gradient(top,#151515,#040404);background-image:-o-linear-gradient(top,#151515,#040404);background-image:linear-gradient(to bottom,#151515,#040404);background-repeat:repeat-x;border-color:#040404 #040404 #000;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff151515',endColorstr='#ff040404',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.navbar-inverse .btn-navbar:hover,.navbar-inverse .btn-navbar:focus,.navbar-inverse .btn-navbar:active,.navbar-inverse .btn-navbar.active,.navbar-inverse .btn-navbar.disabled,.navbar-inverse .btn-navbar[disabled]{color:#fff;background-color:#040404;*background-color:#000}.navbar-inverse .btn-navbar:active,.navbar-inverse .btn-navbar.active{background-color:#000 \9}.breadcrumb{padding:8px 15px;margin:0 0 20px;list-style:none;background-color:#f5f5f5;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.breadcrumb>li{display:inline-block;*display:inline;text-shadow:0 1px 0 #fff;*zoom:1}.breadcrumb>li>.divider{padding:0 5px;color:#ccc}.breadcrumb>.active{color:#999}.pagination{margin:20px 0}.pagination ul{display:inline-block;*display:inline;margin-bottom:0;margin-left:0;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;*zoom:1;-webkit-box-shadow:0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:0 1px 2px rgba(0,0,0,0.05);box-shadow:0 1px 2px rgba(0,0,0,0.05)}.pagination ul>li{display:inline}.pagination ul>li>a,.pagination ul>li>span{float:left;padding:4px 12px;line-height:20px;text-decoration:none;background-color:#fff;border:1px solid #ddd;border-left-width:0}.pagination ul>li>a:hover,.pagination ul>li>a:focus,.pagination ul>.active>a,.pagination ul>.active>span{background-color:#f5f5f5}.pagination ul>.active>a,.pagination ul>.active>span{color:#999;cursor:default}.pagination ul>.disabled>span,.pagination ul>.disabled>a,.pagination ul>.disabled>a:hover,.pagination ul>.disabled>a:focus{color:#999;cursor:default;background-color:transparent}.pagination ul>li:first-child>a,.pagination ul>li:first-child>span{border-left-width:1px;-webkit-border-bottom-left-radius:4px;border-bottom-left-radius:4px;-webkit-border-top-left-radius:4px;border-top-left-radius:4px;-moz-border-radius-bottomleft:4px;-moz-border-radius-topleft:4px}.pagination ul>li:last-child>a,.pagination ul>li:last-child>span{-webkit-border-top-right-radius:4px;border-top-right-radius:4px;-webkit-border-bottom-right-radius:4px;border-bottom-right-radius:4px;-moz-border-radius-topright:4px;-moz-border-radius-bottomright:4px}.pagination-centered{text-align:center}.pagination-right{text-align:right}.pagination-large ul>li>a,.pagination-large ul>li>span{padding:11px 19px;font-size:17.5px}.pagination-large ul>li:first-child>a,.pagination-large ul>li:first-child>span{-webkit-border-bottom-left-radius:6px;border-bottom-left-radius:6px;-webkit-border-top-left-radius:6px;border-top-left-radius:6px;-moz-border-radius-bottomleft:6px;-moz-border-radius-topleft:6px}.pagination-large ul>li:last-child>a,.pagination-large ul>li:last-child>span{-webkit-border-top-right-radius:6px;border-top-right-radius:6px;-webkit-border-bottom-right-radius:6px;border-bottom-right-radius:6px;-moz-border-radius-topright:6px;-moz-border-radius-bottomright:6px}.pagination-mini ul>li:first-child>a,.pagination-small ul>li:first-child>a,.pagination-mini ul>li:first-child>span,.pagination-small ul>li:first-child>span{-webkit-border-bottom-left-radius:3px;border-bottom-left-radius:3px;-webkit-border-top-left-radius:3px;border-top-left-radius:3px;-moz-border-radius-bottomleft:3px;-moz-border-radius-topleft:3px}.pagination-mini ul>li:last-child>a,.pagination-small ul>li:last-child>a,.pagination-mini ul>li:last-child>span,.pagination-small ul>li:last-child>span{-webkit-border-top-right-radius:3px;border-top-right-radius:3px;-webkit-border-bottom-right-radius:3px;border-bottom-right-radius:3px;-moz-border-radius-topright:3px;-moz-border-radius-bottomright:3px}.pagination-small ul>li>a,.pagination-small ul>li>span{padding:2px 10px;font-size:11.9px}.pagination-mini ul>li>a,.pagination-mini ul>li>span{padding:0 6px;font-size:10.5px}.pager{margin:20px 0;text-align:center;list-style:none;*zoom:1}.pager:before,.pager:after{display:table;line-height:0;content:""}.pager:after{clear:both}.pager li{display:inline}.pager li>a,.pager li>span{display:inline-block;padding:5px 14px;background-color:#fff;border:1px solid #ddd;-webkit-border-radius:15px;-moz-border-radius:15px;border-radius:15px}.pager li>a:hover,.pager li>a:focus{text-decoration:none;background-color:#f5f5f5}.pager .next>a,.pager .next>span{float:right}.pager .previous>a,.pager .previous>span{float:left}.pager .disabled>a,.pager .disabled>a:hover,.pager .disabled>a:focus,.pager .disabled>span{color:#999;cursor:default;background-color:#fff}.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;background-color:#000}.modal-backdrop.fade{opacity:0}.modal-backdrop,.modal-backdrop.fade.in{opacity:.8;filter:alpha(opacity=80)}.modal{position:fixed;top:10%;left:50%;z-index:1050;width:560px;margin-left:-280px;background-color:#fff;border:1px solid #999;border:1px solid rgba(0,0,0,0.3);*border:1px solid #999;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;outline:0;-webkit-box-shadow:0 3px 7px rgba(0,0,0,0.3);-moz-box-shadow:0 3px 7px rgba(0,0,0,0.3);box-shadow:0 3px 7px rgba(0,0,0,0.3);-webkit-background-clip:padding-box;-moz-background-clip:padding-box;background-clip:padding-box}.modal.fade{top:-25%;-webkit-transition:opacity .3s linear,top .3s ease-out;-moz-transition:opacity .3s linear,top .3s ease-out;-o-transition:opacity .3s linear,top .3s ease-out;transition:opacity .3s linear,top .3s ease-out}.modal.fade.in{top:10%}.modal-header{padding:9px 15px;border-bottom:1px solid #eee}.modal-header .close{margin-top:2px}.modal-header h3{margin:0;line-height:30px}.modal-body{position:relative;max-height:400px;padding:15px;overflow-y:auto}.modal-form{margin-bottom:0}.modal-footer{padding:14px 15px 15px;margin-bottom:0;text-align:right;background-color:#f5f5f5;border-top:1px solid #ddd;-webkit-border-radius:0 0 6px 6px;-moz-border-radius:0 0 6px 6px;border-radius:0 0 6px 6px;*zoom:1;-webkit-box-shadow:inset 0 1px 0 #fff;-moz-box-shadow:inset 0 1px 0 #fff;box-shadow:inset 0 1px 0 #fff}.modal-footer:before,.modal-footer:after{display:table;line-height:0;content:""}.modal-footer:after{clear:both}.modal-footer .btn+.btn{margin-bottom:0;margin-left:5px}.modal-footer .btn-group .btn+.btn{margin-left:-1px}.modal-footer .btn-block+.btn-block{margin-left:0}.tooltip{position:absolute;z-index:1030;display:block;font-size:11px;line-height:1.4;opacity:0;filter:alpha(opacity=0);visibility:visible}.tooltip.in{opacity:.8;filter:alpha(opacity=80)}.tooltip.top{padding:5px 0;margin-top:-3px}.tooltip.right{padding:0 5px;margin-left:3px}.tooltip.bottom{padding:5px 0;margin-top:3px}.tooltip.left{padding:0 5px;margin-left:-3px}.tooltip-inner{max-width:200px;padding:8px;color:#fff;text-align:center;text-decoration:none;background-color:#000;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.tooltip-arrow{position:absolute;width:0;height:0;border-color:transparent;border-style:solid}.tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-top-color:#000;border-width:5px 5px 0}.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-right-color:#000;border-width:5px 5px 5px 0}.tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-left-color:#000;border-width:5px 0 5px 5px}.tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-bottom-color:#000;border-width:0 5px 5px}.popover{position:absolute;top:0;left:0;z-index:1010;display:none;max-width:276px;padding:1px;text-align:left;white-space:normal;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.2);-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,0.2);-moz-box-shadow:0 5px 10px rgba(0,0,0,0.2);box-shadow:0 5px 10px rgba(0,0,0,0.2);-webkit-background-clip:padding-box;-moz-background-clip:padding;background-clip:padding-box}.popover.top{margin-top:-10px}.popover.right{margin-left:10px}.popover.bottom{margin-top:10px}.popover.left{margin-left:-10px}.popover-title{padding:8px 14px;margin:0;font-size:14px;font-weight:normal;line-height:18px;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;-webkit-border-radius:5px 5px 0 0;-moz-border-radius:5px 5px 0 0;border-radius:5px 5px 0 0}.popover-title:empty{display:none}.popover-content{padding:9px 14px}.popover .arrow,.popover .arrow:after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.popover .arrow{border-width:11px}.popover .arrow:after{border-width:10px;content:""}.popover.top .arrow{bottom:-11px;left:50%;margin-left:-11px;border-top-color:#999;border-top-color:rgba(0,0,0,0.25);border-bottom-width:0}.popover.top .arrow:after{bottom:1px;margin-left:-10px;border-top-color:#fff;border-bottom-width:0}.popover.right .arrow{top:50%;left:-11px;margin-top:-11px;border-right-color:#999;border-right-color:rgba(0,0,0,0.25);border-left-width:0}.popover.right .arrow:after{bottom:-10px;left:1px;border-right-color:#fff;border-left-width:0}.popover.bottom .arrow{top:-11px;left:50%;margin-left:-11px;border-bottom-color:#999;border-bottom-color:rgba(0,0,0,0.25);border-top-width:0}.popover.bottom .arrow:after{top:1px;margin-left:-10px;border-bottom-color:#fff;border-top-width:0}.popover.left .arrow{top:50%;right:-11px;margin-top:-11px;border-left-color:#999;border-left-color:rgba(0,0,0,0.25);border-right-width:0}.popover.left .arrow:after{right:1px;bottom:-10px;border-left-color:#fff;border-right-width:0}.thumbnails{margin-left:-20px;list-style:none;*zoom:1}.thumbnails:before,.thumbnails:after{display:table;line-height:0;content:""}.thumbnails:after{clear:both}.row-fluid .thumbnails{margin-left:0}.thumbnails>li{float:left;margin-bottom:20px;margin-left:20px}.thumbnail{display:block;padding:4px;line-height:20px;border:1px solid #ddd;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;-webkit-box-shadow:0 1px 3px rgba(0,0,0,0.055);-moz-box-shadow:0 1px 3px rgba(0,0,0,0.055);box-shadow:0 1px 3px rgba(0,0,0,0.055);-webkit-transition:all .2s ease-in-out;-moz-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;transition:all .2s ease-in-out}a.thumbnail:hover,a.thumbnail:focus{border-color:#08c;-webkit-box-shadow:0 1px 4px rgba(0,105,214,0.25);-moz-box-shadow:0 1px 4px rgba(0,105,214,0.25);box-shadow:0 1px 4px rgba(0,105,214,0.25)}.thumbnail>img{display:block;max-width:100%;margin-right:auto;margin-left:auto}.thumbnail .caption{padding:9px;color:#555}.media,.media-body{overflow:hidden;*overflow:visible;zoom:1}.media,.media .media{margin-top:15px}.media:first-child{margin-top:0}.media-object{display:block}.media-heading{margin:0 0 5px}.media>.pull-left{margin-right:10px}.media>.pull-right{margin-left:10px}.media-list{margin-left:0;list-style:none}.label,.badge{display:inline-block;padding:2px 4px;font-size:11.844px;font-weight:bold;line-height:14px;color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);white-space:nowrap;vertical-align:baseline;background-color:#999}.label{-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.badge{padding-right:9px;padding-left:9px;-webkit-border-radius:9px;-moz-border-radius:9px;border-radius:9px}.label:empty,.badge:empty{display:none}a.label:hover,a.label:focus,a.badge:hover,a.badge:focus{color:#fff;text-decoration:none;cursor:pointer}.label-important,.badge-important{background-color:#b94a48}.label-important[href],.badge-important[href]{background-color:#953b39}.label-warning,.badge-warning{background-color:#f89406}.label-warning[href],.badge-warning[href]{background-color:#c67605}.label-success,.badge-success{background-color:#468847}.label-success[href],.badge-success[href]{background-color:#356635}.label-info,.badge-info{background-color:#3a87ad}.label-info[href],.badge-info[href]{background-color:#2d6987}.label-inverse,.badge-inverse{background-color:#333}.label-inverse[href],.badge-inverse[href]{background-color:#1a1a1a}.btn .label,.btn .badge{position:relative;top:-1px}.btn-mini .label,.btn-mini .badge{top:0}@-webkit-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-moz-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-ms-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-o-keyframes progress-bar-stripes{from{background-position:0 0}to{background-position:40px 0}}@keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}.progress{height:20px;margin-bottom:20px;overflow:hidden;background-color:#f7f7f7;background-image:-moz-linear-gradient(top,#f5f5f5,#f9f9f9);background-image:-webkit-gradient(linear,0 0,0 100%,from(#f5f5f5),to(#f9f9f9));background-image:-webkit-linear-gradient(top,#f5f5f5,#f9f9f9);background-image:-o-linear-gradient(top,#f5f5f5,#f9f9f9);background-image:linear-gradient(to bottom,#f5f5f5,#f9f9f9);background-repeat:repeat-x;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5',endColorstr='#fff9f9f9',GradientType=0);-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.1);-moz-box-shadow:inset 0 1px 2px rgba(0,0,0,0.1);box-shadow:inset 0 1px 2px rgba(0,0,0,0.1)}.progress .bar{float:left;width:0;height:100%;font-size:12px;color:#fff;text-align:center;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#0e90d2;background-image:-moz-linear-gradient(top,#149bdf,#0480be);background-image:-webkit-gradient(linear,0 0,0 100%,from(#149bdf),to(#0480be));background-image:-webkit-linear-gradient(top,#149bdf,#0480be);background-image:-o-linear-gradient(top,#149bdf,#0480be);background-image:linear-gradient(to bottom,#149bdf,#0480be);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff149bdf',endColorstr='#ff0480be',GradientType=0);-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);-moz-box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;-webkit-transition:width .6s ease;-moz-transition:width .6s ease;-o-transition:width .6s ease;transition:width .6s ease}.progress .bar+.bar{-webkit-box-shadow:inset 1px 0 0 rgba(0,0,0,0.15),inset 0 -1px 0 rgba(0,0,0,0.15);-moz-box-shadow:inset 1px 0 0 rgba(0,0,0,0.15),inset 0 -1px 0 rgba(0,0,0,0.15);box-shadow:inset 1px 0 0 rgba(0,0,0,0.15),inset 0 -1px 0 rgba(0,0,0,0.15)}.progress-striped .bar{background-color:#149bdf;background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(0.25,rgba(255,255,255,0.15)),color-stop(0.25,transparent),color-stop(0.5,transparent),color-stop(0.5,rgba(255,255,255,0.15)),color-stop(0.75,rgba(255,255,255,0.15)),color-stop(0.75,transparent),to(transparent));background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-moz-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);-webkit-background-size:40px 40px;-moz-background-size:40px 40px;-o-background-size:40px 40px;background-size:40px 40px}.progress.active .bar{-webkit-animation:progress-bar-stripes 2s linear infinite;-moz-animation:progress-bar-stripes 2s linear infinite;-ms-animation:progress-bar-stripes 2s linear infinite;-o-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite}.progress-danger .bar,.progress .bar-danger{background-color:#dd514c;background-image:-moz-linear-gradient(top,#ee5f5b,#c43c35);background-image:-webkit-gradient(linear,0 0,0 100%,from(#ee5f5b),to(#c43c35));background-image:-webkit-linear-gradient(top,#ee5f5b,#c43c35);background-image:-o-linear-gradient(top,#ee5f5b,#c43c35);background-image:linear-gradient(to bottom,#ee5f5b,#c43c35);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b',endColorstr='#ffc43c35',GradientType=0)}.progress-danger.progress-striped .bar,.progress-striped .bar-danger{background-color:#ee5f5b;background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(0.25,rgba(255,255,255,0.15)),color-stop(0.25,transparent),color-stop(0.5,transparent),color-stop(0.5,rgba(255,255,255,0.15)),color-stop(0.75,rgba(255,255,255,0.15)),color-stop(0.75,transparent),to(transparent));background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-moz-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent)}.progress-success .bar,.progress .bar-success{background-color:#5eb95e;background-image:-moz-linear-gradient(top,#62c462,#57a957);background-image:-webkit-gradient(linear,0 0,0 100%,from(#62c462),to(#57a957));background-image:-webkit-linear-gradient(top,#62c462,#57a957);background-image:-o-linear-gradient(top,#62c462,#57a957);background-image:linear-gradient(to bottom,#62c462,#57a957);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462',endColorstr='#ff57a957',GradientType=0)}.progress-success.progress-striped .bar,.progress-striped .bar-success{background-color:#62c462;background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(0.25,rgba(255,255,255,0.15)),color-stop(0.25,transparent),color-stop(0.5,transparent),color-stop(0.5,rgba(255,255,255,0.15)),color-stop(0.75,rgba(255,255,255,0.15)),color-stop(0.75,transparent),to(transparent));background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-moz-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent)}.progress-info .bar,.progress .bar-info{background-color:#4bb1cf;background-image:-moz-linear-gradient(top,#5bc0de,#339bb9);background-image:-webkit-gradient(linear,0 0,0 100%,from(#5bc0de),to(#339bb9));background-image:-webkit-linear-gradient(top,#5bc0de,#339bb9);background-image:-o-linear-gradient(top,#5bc0de,#339bb9);background-image:linear-gradient(to bottom,#5bc0de,#339bb9);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de',endColorstr='#ff339bb9',GradientType=0)}.progress-info.progress-striped .bar,.progress-striped .bar-info{background-color:#5bc0de;background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(0.25,rgba(255,255,255,0.15)),color-stop(0.25,transparent),color-stop(0.5,transparent),color-stop(0.5,rgba(255,255,255,0.15)),color-stop(0.75,rgba(255,255,255,0.15)),color-stop(0.75,transparent),to(transparent));background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-moz-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent)}.progress-warning .bar,.progress .bar-warning{background-color:#faa732;background-image:-moz-linear-gradient(top,#fbb450,#f89406);background-image:-webkit-gradient(linear,0 0,0 100%,from(#fbb450),to(#f89406));background-image:-webkit-linear-gradient(top,#fbb450,#f89406);background-image:-o-linear-gradient(top,#fbb450,#f89406);background-image:linear-gradient(to bottom,#fbb450,#f89406);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450',endColorstr='#fff89406',GradientType=0)}.progress-warning.progress-striped .bar,.progress-striped .bar-warning{background-color:#fbb450;background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(0.25,rgba(255,255,255,0.15)),color-stop(0.25,transparent),color-stop(0.5,transparent),color-stop(0.5,rgba(255,255,255,0.15)),color-stop(0.75,rgba(255,255,255,0.15)),color-stop(0.75,transparent),to(transparent));background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-moz-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent)}.accordion{margin-bottom:20px}.accordion-group{margin-bottom:2px;border:1px solid #e5e5e5;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.accordion-heading{border-bottom:0}.accordion-heading .accordion-toggle{display:block;padding:8px 15px}.accordion-toggle{cursor:pointer}.accordion-inner{padding:9px 15px;border-top:1px solid #e5e5e5}.carousel{position:relative;margin-bottom:20px;line-height:1}.carousel-inner{position:relative;width:100%;overflow:hidden}.carousel-inner>.item{position:relative;display:none;-webkit-transition:.6s ease-in-out left;-moz-transition:.6s ease-in-out left;-o-transition:.6s ease-in-out left;transition:.6s ease-in-out left}.carousel-inner>.item>img,.carousel-inner>.item>a>img{display:block;line-height:1}.carousel-inner>.active,.carousel-inner>.next,.carousel-inner>.prev{display:block}.carousel-inner>.active{left:0}.carousel-inner>.next,.carousel-inner>.prev{position:absolute;top:0;width:100%}.carousel-inner>.next{left:100%}.carousel-inner>.prev{left:-100%}.carousel-inner>.next.left,.carousel-inner>.prev.right{left:0}.carousel-inner>.active.left{left:-100%}.carousel-inner>.active.right{left:100%}.carousel-control{position:absolute;top:40%;left:15px;width:40px;height:40px;margin-top:-20px;font-size:60px;font-weight:100;line-height:30px;color:#fff;text-align:center;background:#222;border:3px solid #fff;-webkit-border-radius:23px;-moz-border-radius:23px;border-radius:23px;opacity:.5;filter:alpha(opacity=50)}.carousel-control.right{right:15px;left:auto}.carousel-control:hover,.carousel-control:focus{color:#fff;text-decoration:none;opacity:.9;filter:alpha(opacity=90)}.carousel-indicators{position:absolute;top:15px;right:15px;z-index:5;margin:0;list-style:none}.carousel-indicators li{display:block;float:left;width:10px;height:10px;margin-left:5px;text-indent:-999px;background-color:#ccc;background-color:rgba(255,255,255,0.25);border-radius:5px}.carousel-indicators .active{background-color:#fff}.carousel-caption{position:absolute;right:0;bottom:0;left:0;padding:15px;background:#333;background:rgba(0,0,0,0.75)}.carousel-caption h4,.carousel-caption p{line-height:20px;color:#fff}.carousel-caption h4{margin:0 0 5px}.carousel-caption p{margin-bottom:0}.hero-unit{padding:60px;margin-bottom:30px;font-size:18px;font-weight:200;line-height:30px;color:inherit;background-color:#eee;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px}.hero-unit h1{margin-bottom:0;font-size:60px;line-height:1;letter-spacing:-1px;color:inherit}.hero-unit li{line-height:30px}.pull-right{float:right}.pull-left{float:left}.hide{display:none}.show{display:block}.invisible{visibility:hidden}.affix{position:fixed} diff --git a/webroot/bootstrap/img/glyphicons-halflings-white.png b/webroot/bootstrap/img/glyphicons-halflings-white.png deleted file mode 100644 index 3bf6484a..00000000 Binary files a/webroot/bootstrap/img/glyphicons-halflings-white.png and /dev/null differ diff --git a/webroot/bootstrap/img/glyphicons-halflings.png b/webroot/bootstrap/img/glyphicons-halflings.png deleted file mode 100644 index a9969993..00000000 Binary files a/webroot/bootstrap/img/glyphicons-halflings.png and /dev/null differ diff --git a/webroot/bootstrap/js/bootstrap.js b/webroot/bootstrap/js/bootstrap.js deleted file mode 100644 index c298ee42..00000000 --- a/webroot/bootstrap/js/bootstrap.js +++ /dev/null @@ -1,2276 +0,0 @@ -/* =================================================== - * bootstrap-transition.js v2.3.1 - * http://twitter.github.com/bootstrap/javascript.html#transitions - * =================================================== - * Copyright 2012 Twitter, Inc. - * - * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ========================================================== */ - - -!function ($) { - - "use strict"; // jshint ;_; - - - /* CSS TRANSITION SUPPORT (http://www.modernizr.com/) - * ======================================================= */ - - $(function () { - - $.support.transition = (function () { - - var transitionEnd = (function () { - - var el = document.createElement('bootstrap') - , transEndEventNames = { - 'WebkitTransition' : 'webkitTransitionEnd' - , 'MozTransition' : 'transitionend' - , 'OTransition' : 'oTransitionEnd otransitionend' - , 'transition' : 'transitionend' - } - , name - - for (name in transEndEventNames){ - if (el.style[name] !== undefined) { - return transEndEventNames[name] - } - } - - }()) - - return transitionEnd && { - end: transitionEnd - } - - })() - - }) - -}(window.jQuery);/* ========================================================== - * bootstrap-alert.js v2.3.1 - * http://twitter.github.com/bootstrap/javascript.html#alerts - * ========================================================== - * Copyright 2012 Twitter, Inc. - * - * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ========================================================== */ - - -!function ($) { - - "use strict"; // jshint ;_; - - - /* ALERT CLASS DEFINITION - * ====================== */ - - var dismiss = '[data-dismiss="alert"]' - , Alert = function (el) { - $(el).on('click', dismiss, this.close) - } - - Alert.prototype.close = function (e) { - var $this = $(this) - , selector = $this.attr('data-target') - , $parent - - if (!selector) { - selector = $this.attr('href') - selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7 - } - - $parent = $(selector) - - e && e.preventDefault() - - $parent.length || ($parent = $this.hasClass('alert') ? $this : $this.parent()) - - $parent.trigger(e = $.Event('close')) - - if (e.isDefaultPrevented()) return - - $parent.removeClass('in') - - function removeElement() { - $parent - .trigger('closed') - .remove() - } - - $.support.transition && $parent.hasClass('fade') ? - $parent.on($.support.transition.end, removeElement) : - removeElement() - } - - - /* ALERT PLUGIN DEFINITION - * ======================= */ - - var old = $.fn.alert - - $.fn.alert = function (option) { - return this.each(function () { - var $this = $(this) - , data = $this.data('alert') - if (!data) $this.data('alert', (data = new Alert(this))) - if (typeof option == 'string') data[option].call($this) - }) - } - - $.fn.alert.Constructor = Alert - - - /* ALERT NO CONFLICT - * ================= */ - - $.fn.alert.noConflict = function () { - $.fn.alert = old - return this - } - - - /* ALERT DATA-API - * ============== */ - - $(document).on('click.alert.data-api', dismiss, Alert.prototype.close) - -}(window.jQuery);/* ============================================================ - * bootstrap-button.js v2.3.1 - * http://twitter.github.com/bootstrap/javascript.html#buttons - * ============================================================ - * Copyright 2012 Twitter, Inc. - * - * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================ */ - - -!function ($) { - - "use strict"; // jshint ;_; - - - /* BUTTON PUBLIC CLASS DEFINITION - * ============================== */ - - var Button = function (element, options) { - this.$element = $(element) - this.options = $.extend({}, $.fn.button.defaults, options) - } - - Button.prototype.setState = function (state) { - var d = 'disabled' - , $el = this.$element - , data = $el.data() - , val = $el.is('input') ? 'val' : 'html' - - state = state + 'Text' - data.resetText || $el.data('resetText', $el[val]()) - - $el[val](data[state] || this.options[state]) - - // push to event loop to allow forms to submit - setTimeout(function () { - state == 'loadingText' ? - $el.addClass(d).attr(d, d) : - $el.removeClass(d).removeAttr(d) - }, 0) - } - - Button.prototype.toggle = function () { - var $parent = this.$element.closest('[data-toggle="buttons-radio"]') - - $parent && $parent - .find('.active') - .removeClass('active') - - this.$element.toggleClass('active') - } - - - /* BUTTON PLUGIN DEFINITION - * ======================== */ - - var old = $.fn.button - - $.fn.button = function (option) { - return this.each(function () { - var $this = $(this) - , data = $this.data('button') - , options = typeof option == 'object' && option - if (!data) $this.data('button', (data = new Button(this, options))) - if (option == 'toggle') data.toggle() - else if (option) data.setState(option) - }) - } - - $.fn.button.defaults = { - loadingText: 'loading...' - } - - $.fn.button.Constructor = Button - - - /* BUTTON NO CONFLICT - * ================== */ - - $.fn.button.noConflict = function () { - $.fn.button = old - return this - } - - - /* BUTTON DATA-API - * =============== */ - - $(document).on('click.button.data-api', '[data-toggle^=button]', function (e) { - var $btn = $(e.target) - if (!$btn.hasClass('btn')) $btn = $btn.closest('.btn') - $btn.button('toggle') - }) - -}(window.jQuery);/* ========================================================== - * bootstrap-carousel.js v2.3.1 - * http://twitter.github.com/bootstrap/javascript.html#carousel - * ========================================================== - * Copyright 2012 Twitter, Inc. - * - * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ========================================================== */ - - -!function ($) { - - "use strict"; // jshint ;_; - - - /* CAROUSEL CLASS DEFINITION - * ========================= */ - - var Carousel = function (element, options) { - this.$element = $(element) - this.$indicators = this.$element.find('.carousel-indicators') - this.options = options - this.options.pause == 'hover' && this.$element - .on('mouseenter', $.proxy(this.pause, this)) - .on('mouseleave', $.proxy(this.cycle, this)) - } - - Carousel.prototype = { - - cycle: function (e) { - if (!e) this.paused = false - if (this.interval) clearInterval(this.interval); - this.options.interval - && !this.paused - && (this.interval = setInterval($.proxy(this.next, this), this.options.interval)) - return this - } - - , getActiveIndex: function () { - this.$active = this.$element.find('.item.active') - this.$items = this.$active.parent().children() - return this.$items.index(this.$active) - } - - , to: function (pos) { - var activeIndex = this.getActiveIndex() - , that = this - - if (pos > (this.$items.length - 1) || pos < 0) return - - if (this.sliding) { - return this.$element.one('slid', function () { - that.to(pos) - }) - } - - if (activeIndex == pos) { - return this.pause().cycle() - } - - return this.slide(pos > activeIndex ? 'next' : 'prev', $(this.$items[pos])) - } - - , pause: function (e) { - if (!e) this.paused = true - if (this.$element.find('.next, .prev').length && $.support.transition.end) { - this.$element.trigger($.support.transition.end) - this.cycle(true) - } - clearInterval(this.interval) - this.interval = null - return this - } - - , next: function () { - if (this.sliding) return - return this.slide('next') - } - - , prev: function () { - if (this.sliding) return - return this.slide('prev') - } - - , slide: function (type, next) { - var $active = this.$element.find('.item.active') - , $next = next || $active[type]() - , isCycling = this.interval - , direction = type == 'next' ? 'left' : 'right' - , fallback = type == 'next' ? 'first' : 'last' - , that = this - , e - - this.sliding = true - - isCycling && this.pause() - - $next = $next.length ? $next : this.$element.find('.item')[fallback]() - - e = $.Event('slide', { - relatedTarget: $next[0] - , direction: direction - }) - - if ($next.hasClass('active')) return - - if (this.$indicators.length) { - this.$indicators.find('.active').removeClass('active') - this.$element.one('slid', function () { - var $nextIndicator = $(that.$indicators.children()[that.getActiveIndex()]) - $nextIndicator && $nextIndicator.addClass('active') - }) - } - - if ($.support.transition && this.$element.hasClass('slide')) { - this.$element.trigger(e) - if (e.isDefaultPrevented()) return - $next.addClass(type) - $next[0].offsetWidth // force reflow - $active.addClass(direction) - $next.addClass(direction) - this.$element.one($.support.transition.end, function () { - $next.removeClass([type, direction].join(' ')).addClass('active') - $active.removeClass(['active', direction].join(' ')) - that.sliding = false - setTimeout(function () { that.$element.trigger('slid') }, 0) - }) - } else { - this.$element.trigger(e) - if (e.isDefaultPrevented()) return - $active.removeClass('active') - $next.addClass('active') - this.sliding = false - this.$element.trigger('slid') - } - - isCycling && this.cycle() - - return this - } - - } - - - /* CAROUSEL PLUGIN DEFINITION - * ========================== */ - - var old = $.fn.carousel - - $.fn.carousel = function (option) { - return this.each(function () { - var $this = $(this) - , data = $this.data('carousel') - , options = $.extend({}, $.fn.carousel.defaults, typeof option == 'object' && option) - , action = typeof option == 'string' ? option : options.slide - if (!data) $this.data('carousel', (data = new Carousel(this, options))) - if (typeof option == 'number') data.to(option) - else if (action) data[action]() - else if (options.interval) data.pause().cycle() - }) - } - - $.fn.carousel.defaults = { - interval: 5000 - , pause: 'hover' - } - - $.fn.carousel.Constructor = Carousel - - - /* CAROUSEL NO CONFLICT - * ==================== */ - - $.fn.carousel.noConflict = function () { - $.fn.carousel = old - return this - } - - /* CAROUSEL DATA-API - * ================= */ - - $(document).on('click.carousel.data-api', '[data-slide], [data-slide-to]', function (e) { - var $this = $(this), href - , $target = $($this.attr('data-target') || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) //strip for ie7 - , options = $.extend({}, $target.data(), $this.data()) - , slideIndex - - $target.carousel(options) - - if (slideIndex = $this.attr('data-slide-to')) { - $target.data('carousel').pause().to(slideIndex).cycle() - } - - e.preventDefault() - }) - -}(window.jQuery);/* ============================================================= - * bootstrap-collapse.js v2.3.1 - * http://twitter.github.com/bootstrap/javascript.html#collapse - * ============================================================= - * Copyright 2012 Twitter, Inc. - * - * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================ */ - - -!function ($) { - - "use strict"; // jshint ;_; - - - /* COLLAPSE PUBLIC CLASS DEFINITION - * ================================ */ - - var Collapse = function (element, options) { - this.$element = $(element) - this.options = $.extend({}, $.fn.collapse.defaults, options) - - if (this.options.parent) { - this.$parent = $(this.options.parent) - } - - this.options.toggle && this.toggle() - } - - Collapse.prototype = { - - constructor: Collapse - - , dimension: function () { - var hasWidth = this.$element.hasClass('width') - return hasWidth ? 'width' : 'height' - } - - , show: function () { - var dimension - , scroll - , actives - , hasData - - if (this.transitioning || this.$element.hasClass('in')) return - - dimension = this.dimension() - scroll = $.camelCase(['scroll', dimension].join('-')) - actives = this.$parent && this.$parent.find('> .accordion-group > .in') - - if (actives && actives.length) { - hasData = actives.data('collapse') - if (hasData && hasData.transitioning) return - actives.collapse('hide') - hasData || actives.data('collapse', null) - } - - this.$element[dimension](0) - this.transition('addClass', $.Event('show'), 'shown') - $.support.transition && this.$element[dimension](this.$element[0][scroll]) - } - - , hide: function () { - var dimension - if (this.transitioning || !this.$element.hasClass('in')) return - dimension = this.dimension() - this.reset(this.$element[dimension]()) - this.transition('removeClass', $.Event('hide'), 'hidden') - this.$element[dimension](0) - } - - , reset: function (size) { - var dimension = this.dimension() - - this.$element - .removeClass('collapse') - [dimension](size || 'auto') - [0].offsetWidth - - this.$element[size !== null ? 'addClass' : 'removeClass']('collapse') - - return this - } - - , transition: function (method, startEvent, completeEvent) { - var that = this - , complete = function () { - if (startEvent.type == 'show') that.reset() - that.transitioning = 0 - that.$element.trigger(completeEvent) - } - - this.$element.trigger(startEvent) - - if (startEvent.isDefaultPrevented()) return - - this.transitioning = 1 - - this.$element[method]('in') - - $.support.transition && this.$element.hasClass('collapse') ? - this.$element.one($.support.transition.end, complete) : - complete() - } - - , toggle: function () { - this[this.$element.hasClass('in') ? 'hide' : 'show']() - } - - } - - - /* COLLAPSE PLUGIN DEFINITION - * ========================== */ - - var old = $.fn.collapse - - $.fn.collapse = function (option) { - return this.each(function () { - var $this = $(this) - , data = $this.data('collapse') - , options = $.extend({}, $.fn.collapse.defaults, $this.data(), typeof option == 'object' && option) - if (!data) $this.data('collapse', (data = new Collapse(this, options))) - if (typeof option == 'string') data[option]() - }) - } - - $.fn.collapse.defaults = { - toggle: true - } - - $.fn.collapse.Constructor = Collapse - - - /* COLLAPSE NO CONFLICT - * ==================== */ - - $.fn.collapse.noConflict = function () { - $.fn.collapse = old - return this - } - - - /* COLLAPSE DATA-API - * ================= */ - - $(document).on('click.collapse.data-api', '[data-toggle=collapse]', function (e) { - var $this = $(this), href - , target = $this.attr('data-target') - || e.preventDefault() - || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') //strip for ie7 - , option = $(target).data('collapse') ? 'toggle' : $this.data() - $this[$(target).hasClass('in') ? 'addClass' : 'removeClass']('collapsed') - $(target).collapse(option) - }) - -}(window.jQuery);/* ============================================================ - * bootstrap-dropdown.js v2.3.1 - * http://twitter.github.com/bootstrap/javascript.html#dropdowns - * ============================================================ - * Copyright 2012 Twitter, Inc. - * - * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================ */ - - -!function ($) { - - "use strict"; // jshint ;_; - - - /* DROPDOWN CLASS DEFINITION - * ========================= */ - - var toggle = '[data-toggle=dropdown]' - , Dropdown = function (element) { - var $el = $(element).on('click.dropdown.data-api', this.toggle) - $('html').on('click.dropdown.data-api', function () { - $el.parent().removeClass('open') - }) - } - - Dropdown.prototype = { - - constructor: Dropdown - - , toggle: function (e) { - var $this = $(this) - , $parent - , isActive - - if ($this.is('.disabled, :disabled')) return - - $parent = getParent($this) - - isActive = $parent.hasClass('open') - - clearMenus() - - if (!isActive) { - $parent.toggleClass('open') - } - - $this.focus() - - return false - } - - , keydown: function (e) { - var $this - , $items - , $active - , $parent - , isActive - , index - - if (!/(38|40|27)/.test(e.keyCode)) return - - $this = $(this) - - e.preventDefault() - e.stopPropagation() - - if ($this.is('.disabled, :disabled')) return - - $parent = getParent($this) - - isActive = $parent.hasClass('open') - - if (!isActive || (isActive && e.keyCode == 27)) { - if (e.which == 27) $parent.find(toggle).focus() - return $this.click() - } - - $items = $('[role=menu] li:not(.divider):visible a', $parent) - - if (!$items.length) return - - index = $items.index($items.filter(':focus')) - - if (e.keyCode == 38 && index > 0) index-- // up - if (e.keyCode == 40 && index < $items.length - 1) index++ // down - if (!~index) index = 0 - - $items - .eq(index) - .focus() - } - - } - - function clearMenus() { - $(toggle).each(function () { - getParent($(this)).removeClass('open') - }) - } - - function getParent($this) { - var selector = $this.attr('data-target') - , $parent - - if (!selector) { - selector = $this.attr('href') - selector = selector && /#/.test(selector) && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7 - } - - $parent = selector && $(selector) - - if (!$parent || !$parent.length) $parent = $this.parent() - - return $parent - } - - - /* DROPDOWN PLUGIN DEFINITION - * ========================== */ - - var old = $.fn.dropdown - - $.fn.dropdown = function (option) { - return this.each(function () { - var $this = $(this) - , data = $this.data('dropdown') - if (!data) $this.data('dropdown', (data = new Dropdown(this))) - if (typeof option == 'string') data[option].call($this) - }) - } - - $.fn.dropdown.Constructor = Dropdown - - - /* DROPDOWN NO CONFLICT - * ==================== */ - - $.fn.dropdown.noConflict = function () { - $.fn.dropdown = old - return this - } - - - /* APPLY TO STANDARD DROPDOWN ELEMENTS - * =================================== */ - - $(document) - .on('click.dropdown.data-api', clearMenus) - .on('click.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation() }) - .on('click.dropdown-menu', function (e) { e.stopPropagation() }) - .on('click.dropdown.data-api' , toggle, Dropdown.prototype.toggle) - .on('keydown.dropdown.data-api', toggle + ', [role=menu]' , Dropdown.prototype.keydown) - -}(window.jQuery); -/* ========================================================= - * bootstrap-modal.js v2.3.1 - * http://twitter.github.com/bootstrap/javascript.html#modals - * ========================================================= - * Copyright 2012 Twitter, Inc. - * - * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ========================================================= */ - - -!function ($) { - - "use strict"; // jshint ;_; - - - /* MODAL CLASS DEFINITION - * ====================== */ - - var Modal = function (element, options) { - this.options = options - this.$element = $(element) - .delegate('[data-dismiss="modal"]', 'click.dismiss.modal', $.proxy(this.hide, this)) - this.options.remote && this.$element.find('.modal-body').load(this.options.remote) - } - - Modal.prototype = { - - constructor: Modal - - , toggle: function () { - return this[!this.isShown ? 'show' : 'hide']() - } - - , show: function () { - var that = this - , e = $.Event('show') - - this.$element.trigger(e) - - if (this.isShown || e.isDefaultPrevented()) return - - this.isShown = true - - this.escape() - - this.backdrop(function () { - var transition = $.support.transition && that.$element.hasClass('fade') - - if (!that.$element.parent().length) { - that.$element.appendTo(document.body) //don't move modals dom position - } - - that.$element.show() - - if (transition) { - that.$element[0].offsetWidth // force reflow - } - - that.$element - .addClass('in') - .attr('aria-hidden', false) - - that.enforceFocus() - - transition ? - that.$element.one($.support.transition.end, function () { that.$element.focus().trigger('shown') }) : - that.$element.focus().trigger('shown') - - }) - } - - , hide: function (e) { - e && e.preventDefault() - - var that = this - - e = $.Event('hide') - - this.$element.trigger(e) - - if (!this.isShown || e.isDefaultPrevented()) return - - this.isShown = false - - this.escape() - - $(document).off('focusin.modal') - - this.$element - .removeClass('in') - .attr('aria-hidden', true) - - $.support.transition && this.$element.hasClass('fade') ? - this.hideWithTransition() : - this.hideModal() - } - - , enforceFocus: function () { - var that = this - $(document).on('focusin.modal', function (e) { - if (that.$element[0] !== e.target && !that.$element.has(e.target).length) { - that.$element.focus() - } - }) - } - - , escape: function () { - var that = this - if (this.isShown && this.options.keyboard) { - this.$element.on('keyup.dismiss.modal', function ( e ) { - e.which == 27 && that.hide() - }) - } else if (!this.isShown) { - this.$element.off('keyup.dismiss.modal') - } - } - - , hideWithTransition: function () { - var that = this - , timeout = setTimeout(function () { - that.$element.off($.support.transition.end) - that.hideModal() - }, 500) - - this.$element.one($.support.transition.end, function () { - clearTimeout(timeout) - that.hideModal() - }) - } - - , hideModal: function () { - var that = this - this.$element.hide() - this.backdrop(function () { - that.removeBackdrop() - that.$element.trigger('hidden') - }) - } - - , removeBackdrop: function () { - this.$backdrop && this.$backdrop.remove() - this.$backdrop = null - } - - , backdrop: function (callback) { - var that = this - , animate = this.$element.hasClass('fade') ? 'fade' : '' - - if (this.isShown && this.options.backdrop) { - var doAnimate = $.support.transition && animate - - this.$backdrop = $('