diff --git a/.travis.yml b/.travis.yml
index 34d38c2c54..df6a7356bf 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,4 +1,4 @@
-dist: trusty
+dist: bionic
notifications:
email:
@@ -9,22 +9,38 @@ notifications:
language: java
-jdk:
- - oraclejdk8
-
matrix:
include:
# On OSX, run with default JDK only.
# - os: osx
- # On Linux, run with specific JDKs only.
- - os: linux
- env: CUSTOM_JDK="oraclejdk8"
+ # On Linux we install latest OpenJDK 1.8 from Ubuntu repositories
+ - name: Linux x86_64
+ arch: amd64
+ - name: Linux aarch64
+ arch: arm64
+
+cache:
+ directories:
+ - $HOME/.m2/repository
before_install:
+ - lscpu
- echo 'MAVEN_OPTS="$MAVEN_OPTS -Xmx1024m -XX:MaxPermSize=512m -XX:+BytecodeVerificationLocal"' >> ~/.mavenrc
- cat ~/.mavenrc
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then export JAVA_HOME=$(/usr/libexec/java_home); fi
- - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then jdk_switcher use "$CUSTOM_JDK"; fi
+
+install: |
+ if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then
+ sudo apt update
+ sudo apt install -y openjdk-8-jdk maven
+ export JAVA_HOME="/usr/lib/jvm/java-8-openjdk-${TRAVIS_CPU_ARCH}/"
+ export PATH="$JAVA_HOME/bin:/usr/share/maven/bin:$PATH"
+ fi
+
+before_script:
+ - java -version
+ - mvn -version
+ - ulimit -c unlimited
script:
- travis_retry mvn -B clean apache-rat:check
diff --git a/LICENSE b/LICENSE
index 7f77f44e73..f49a4e16e6 100644
--- a/LICENSE
+++ b/LICENSE
@@ -15,7 +15,7 @@
"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 (properties) the power, direct or indirect, to cause the
+ "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.
diff --git a/NOTICE b/NOTICE
index 65ebdd0361..086ee9fa17 100644
--- a/NOTICE
+++ b/NOTICE
@@ -1,5 +1,5 @@
Apache RocketMQ
-Copyright 2016-2020 The Apache Software Foundation
+Copyright 2016-2021 The Apache Software Foundation
This product includes software developed at
The Apache Software Foundation (http://www.apache.org/).
diff --git a/README.md b/README.md
index 91d195c341..1b1398cb79 100644
--- a/README.md
+++ b/README.md
@@ -6,7 +6,7 @@
[](https://www.apache.org/licenses/LICENSE-2.0.html)
[](http://isitmaintained.com/project/apache/rocketmq "Average time to resolve an issue")
[](http://isitmaintained.com/project/apache/rocketmq "Percentage of issues still open")
-
+[](https://twitter.com/intent/follow?screen_name=ApacheRocketMQ)
**[Apache RocketMQ](https://rocketmq.apache.org) is a distributed messaging and streaming platform with low latency, high performance and reliability, trillion-level capacity and flexible scalability.**
diff --git a/acl/pom.xml b/acl/pom.xml
index ed5e709d3c..36dae6ad04 100644
--- a/acl/pom.xml
+++ b/acl/pom.xml
@@ -13,7 +13,7 @@
org.apache.rocketmq
rocketmq-all
- 4.8.0-SNAPSHOT
+ 4.8.1-SNAPSHOT
rocketmq-acl
rocketmq-acl ${project.version}
diff --git a/acl/src/main/java/org/apache/rocketmq/acl/plain/RemoteAddressStrategyFactory.java b/acl/src/main/java/org/apache/rocketmq/acl/plain/RemoteAddressStrategyFactory.java
index 0c3548eeb5..6ec90ee3fa 100644
--- a/acl/src/main/java/org/apache/rocketmq/acl/plain/RemoteAddressStrategyFactory.java
+++ b/acl/src/main/java/org/apache/rocketmq/acl/plain/RemoteAddressStrategyFactory.java
@@ -193,7 +193,7 @@ public class RemoteAddressStrategyFactory {
throw new AclException(String.format("RangeRemoteAddressStrategy netaddress examine scope Exception start is %s , end is %s", start, end));
}
}
- return this.end > 0 ? true : false;
+ return this.end > 0;
}
private boolean ipv6Analysis(String[] strArray, int index) {
diff --git a/broker/pom.xml b/broker/pom.xml
index 8d52edbf1f..0137b55678 100644
--- a/broker/pom.xml
+++ b/broker/pom.xml
@@ -13,7 +13,7 @@
org.apache.rocketmq
rocketmq-all
- 4.8.0-SNAPSHOT
+ 4.8.1-SNAPSHOT
4.0.0
diff --git a/broker/src/main/java/org/apache/rocketmq/broker/mqtrace/SendMessageHook.java b/broker/src/main/java/org/apache/rocketmq/broker/mqtrace/SendMessageHook.java
index a74b6d66ce..a89bace193 100644
--- a/broker/src/main/java/org/apache/rocketmq/broker/mqtrace/SendMessageHook.java
+++ b/broker/src/main/java/org/apache/rocketmq/broker/mqtrace/SendMessageHook.java
@@ -17,9 +17,9 @@
package org.apache.rocketmq.broker.mqtrace;
public interface SendMessageHook {
- public String hookName();
+ String hookName();
- public void sendMessageBefore(final SendMessageContext context);
+ void sendMessageBefore(final SendMessageContext context);
- public void sendMessageAfter(final SendMessageContext context);
+ void sendMessageAfter(final SendMessageContext context);
}
diff --git a/broker/src/main/java/org/apache/rocketmq/broker/offset/ConsumerOffsetManager.java b/broker/src/main/java/org/apache/rocketmq/broker/offset/ConsumerOffsetManager.java
index ebc9dd8acc..bd05758759 100644
--- a/broker/src/main/java/org/apache/rocketmq/broker/offset/ConsumerOffsetManager.java
+++ b/broker/src/main/java/org/apache/rocketmq/broker/offset/ConsumerOffsetManager.java
@@ -232,4 +232,20 @@ public class ConsumerOffsetManager extends ConfigManager {
}
}
+ public void removeOffset(final String group) {
+ Iterator>> it = this.offsetTable.entrySet().iterator();
+ while (it.hasNext()) {
+ Entry> next = it.next();
+ String topicAtGroup = next.getKey();
+ if (topicAtGroup.contains(group)) {
+ String[] arrays = topicAtGroup.split(TOPIC_GROUP_SEPARATOR);
+ if (arrays.length == 2 && group.equals(arrays[1])) {
+ it.remove();
+ log.warn("clean group offset {}", topicAtGroup);
+ }
+ }
+ }
+
+ }
+
}
diff --git a/broker/src/main/java/org/apache/rocketmq/broker/out/BrokerOuterAPI.java b/broker/src/main/java/org/apache/rocketmq/broker/out/BrokerOuterAPI.java
index a237bf61ac..de7f3fce81 100644
--- a/broker/src/main/java/org/apache/rocketmq/broker/out/BrokerOuterAPI.java
+++ b/broker/src/main/java/org/apache/rocketmq/broker/out/BrokerOuterAPI.java
@@ -19,7 +19,6 @@ package org.apache.rocketmq.broker.out;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;
-import java.util.Vector;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CountDownLatch;
@@ -123,7 +122,7 @@ public class BrokerOuterAPI {
final int timeoutMills,
final boolean compressed) {
- final List registerBrokerResultList = new Vector<>();
+ final List registerBrokerResultList = new CopyOnWriteArrayList<>();
List nameServerAddressList = this.remotingClient.getNameServerAddressList();
if (nameServerAddressList != null && nameServerAddressList.size() > 0) {
@@ -147,7 +146,7 @@ public class BrokerOuterAPI {
@Override
public void run() {
try {
- RegisterBrokerResult result = registerBroker(namesrvAddr,oneway, timeoutMills,requestHeader,body);
+ RegisterBrokerResult result = registerBroker(namesrvAddr, oneway, timeoutMills, requestHeader, body);
if (result != null) {
registerBrokerResultList.add(result);
}
diff --git a/broker/src/main/java/org/apache/rocketmq/broker/processor/AdminBrokerProcessor.java b/broker/src/main/java/org/apache/rocketmq/broker/processor/AdminBrokerProcessor.java
index dcdb701635..0a1d214b87 100644
--- a/broker/src/main/java/org/apache/rocketmq/broker/processor/AdminBrokerProcessor.java
+++ b/broker/src/main/java/org/apache/rocketmq/broker/processor/AdminBrokerProcessor.java
@@ -714,6 +714,10 @@ public class AdminBrokerProcessor extends AsyncNettyRequestProcessor implements
this.brokerController.getSubscriptionGroupManager().deleteSubscriptionGroupConfig(requestHeader.getGroupName());
+ if (requestHeader.isRemoveOffset()) {
+ this.brokerController.getConsumerOffsetManager().removeOffset(requestHeader.getGroupName());
+ }
+
if (this.brokerController.getBrokerConfig().isAutoDeleteUnusedStats()) {
this.brokerController.getBrokerStatsManager().onGroupDeleted(requestHeader.getGroupName());
}
diff --git a/broker/src/main/java/org/apache/rocketmq/broker/processor/PullMessageProcessor.java b/broker/src/main/java/org/apache/rocketmq/broker/processor/PullMessageProcessor.java
index 957dbbaaa3..8879a722fc 100644
--- a/broker/src/main/java/org/apache/rocketmq/broker/processor/PullMessageProcessor.java
+++ b/broker/src/main/java/org/apache/rocketmq/broker/processor/PullMessageProcessor.java
@@ -584,7 +584,7 @@ public class PullMessageProcessor extends AsyncNettyRequestProcessor implements
this.brokerController.getPullMessageExecutor().submit(new RequestTask(run, channel, request));
}
- public void registerConsumeMessageHook(List sendMessageHookList) {
- this.consumeMessageHookList = sendMessageHookList;
+ public void registerConsumeMessageHook(List consumeMessageHookList) {
+ this.consumeMessageHookList = consumeMessageHookList;
}
}
diff --git a/broker/src/main/java/org/apache/rocketmq/broker/processor/ReplyMessageProcessor.java b/broker/src/main/java/org/apache/rocketmq/broker/processor/ReplyMessageProcessor.java
index 565857a347..2890fc4db7 100644
--- a/broker/src/main/java/org/apache/rocketmq/broker/processor/ReplyMessageProcessor.java
+++ b/broker/src/main/java/org/apache/rocketmq/broker/processor/ReplyMessageProcessor.java
@@ -251,28 +251,29 @@ public class ReplyMessageProcessor extends AbstractSendMessageProcessor implemen
// Failed
case CREATE_MAPEDFILE_FAILED:
- log.info("create mapped file failed, server is busy or broken.");
+ log.warn("create mapped file failed, server is busy or broken.");
break;
case MESSAGE_ILLEGAL:
- log.info(
+ log.warn(
"the message is illegal, maybe msg properties length limit 32k.");
break;
case PROPERTIES_SIZE_EXCEEDED:
- log.info(
+ log.warn(
"the message is illegal, maybe msg body or properties length not matched. msg body length limit 128k.");
break;
case SERVICE_NOT_AVAILABLE:
- log.info(
- "service not available now, maybe disk full, maybe your broker machine memory too small.");
+ log.warn(
+ "service not available now. It may be caused by one of the following reasons: " +
+ "the broker's disk is full, messages are put to the slave, message store has been shut down, etc.");
break;
case OS_PAGECACHE_BUSY:
- log.info("[PC_SYNCHRONIZED]broker busy, start flow control for a while");
+ log.warn("[PC_SYNCHRONIZED]broker busy, start flow control for a while");
break;
case UNKNOWN_ERROR:
- log.info("UNKNOWN_ERROR");
+ log.warn("UNKNOWN_ERROR");
break;
default:
- log.info("UNKNOWN_ERROR DEFAULT");
+ log.warn("UNKNOWN_ERROR DEFAULT");
break;
}
diff --git a/broker/src/main/java/org/apache/rocketmq/broker/processor/SendMessageProcessor.java b/broker/src/main/java/org/apache/rocketmq/broker/processor/SendMessageProcessor.java
index 20b5cfaae8..724cf54c81 100644
--- a/broker/src/main/java/org/apache/rocketmq/broker/processor/SendMessageProcessor.java
+++ b/broker/src/main/java/org/apache/rocketmq/broker/processor/SendMessageProcessor.java
@@ -218,6 +218,8 @@ public class SendMessageProcessor extends AbstractSendMessageProcessor implement
String originMsgId = MessageAccessor.getOriginMessageId(msgExt);
MessageAccessor.setOriginMessageId(msgInner, UtilAll.isBlank(originMsgId) ? msgExt.getMsgId() : originMsgId);
+ msgInner.setPropertiesString(MessageDecoder.messageProperties2String(msgExt.getProperties()));
+
CompletableFuture putMessageResult = this.brokerController.getMessageStore().asyncPutMessage(msgInner);
return putMessageResult.thenApply((r) -> {
if (r != null) {
@@ -480,7 +482,8 @@ public class SendMessageProcessor extends AbstractSendMessageProcessor implement
case SERVICE_NOT_AVAILABLE:
response.setCode(ResponseCode.SERVICE_NOT_AVAILABLE);
response.setRemark(
- "service not available now, maybe disk full, " + diskUtil() + ", maybe your broker machine memory too small.");
+ "service not available now. It may be caused by one of the following reasons: " +
+ "the broker's disk is full [" + diskUtil() + "], messages are put to the slave, message store has been shut down, etc.");
break;
case OS_PAGECACHE_BUSY:
response.setCode(ResponseCode.SYSTEM_ERROR);
diff --git a/broker/src/main/java/org/apache/rocketmq/broker/topic/TopicConfigManager.java b/broker/src/main/java/org/apache/rocketmq/broker/topic/TopicConfigManager.java
index 86f606593f..1f2bb4d8ba 100644
--- a/broker/src/main/java/org/apache/rocketmq/broker/topic/TopicConfigManager.java
+++ b/broker/src/main/java/org/apache/rocketmq/broker/topic/TopicConfigManager.java
@@ -45,7 +45,7 @@ public class TopicConfigManager extends ConfigManager {
private static final long LOCK_TIMEOUT_MILLIS = 3000;
private static final int SCHEDULE_TOPIC_QUEUE_NUM = 18;
- private transient final Lock lockTopicConfigTable = new ReentrantLock();
+ private transient final Lock topicConfigTableLock = new ReentrantLock();
private final ConcurrentMap topicConfigTable =
new ConcurrentHashMap(1024);
@@ -159,7 +159,7 @@ public class TopicConfigManager extends ConfigManager {
boolean createNew = false;
try {
- if (this.lockTopicConfigTable.tryLock(LOCK_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS)) {
+ if (this.topicConfigTableLock.tryLock(LOCK_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS)) {
try {
topicConfig = this.topicConfigTable.get(topic);
if (topicConfig != null)
@@ -176,9 +176,7 @@ public class TopicConfigManager extends ConfigManager {
if (PermName.isInherited(defaultTopicConfig.getPerm())) {
topicConfig = new TopicConfig(topic);
- int queueNums =
- clientDefaultTopicQueueNums > defaultTopicConfig.getWriteQueueNums() ? defaultTopicConfig
- .getWriteQueueNums() : clientDefaultTopicQueueNums;
+ int queueNums = Math.min(clientDefaultTopicQueueNums, defaultTopicConfig.getWriteQueueNums());
if (queueNums < 0) {
queueNums = 0;
@@ -213,7 +211,7 @@ public class TopicConfigManager extends ConfigManager {
this.persist();
}
} finally {
- this.lockTopicConfigTable.unlock();
+ this.topicConfigTableLock.unlock();
}
}
} catch (InterruptedException e) {
@@ -239,7 +237,7 @@ public class TopicConfigManager extends ConfigManager {
boolean createNew = false;
try {
- if (this.lockTopicConfigTable.tryLock(LOCK_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS)) {
+ if (this.topicConfigTableLock.tryLock(LOCK_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS)) {
try {
topicConfig = this.topicConfigTable.get(topic);
if (topicConfig != null)
@@ -257,7 +255,7 @@ public class TopicConfigManager extends ConfigManager {
this.dataVersion.nextVersion();
this.persist();
} finally {
- this.lockTopicConfigTable.unlock();
+ this.topicConfigTableLock.unlock();
}
}
} catch (InterruptedException e) {
@@ -279,7 +277,7 @@ public class TopicConfigManager extends ConfigManager {
boolean createNew = false;
try {
- if (this.lockTopicConfigTable.tryLock(LOCK_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS)) {
+ if (this.topicConfigTableLock.tryLock(LOCK_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS)) {
try {
topicConfig = this.topicConfigTable.get(TopicValidator.RMQ_SYS_TRANS_CHECK_MAX_TIME_TOPIC);
if (topicConfig != null)
@@ -297,7 +295,7 @@ public class TopicConfigManager extends ConfigManager {
this.dataVersion.nextVersion();
this.persist();
} finally {
- this.lockTopicConfigTable.unlock();
+ this.topicConfigTableLock.unlock();
}
}
} catch (InterruptedException e) {
diff --git a/broker/src/main/java/org/apache/rocketmq/broker/transaction/queue/TransactionalMessageServiceImpl.java b/broker/src/main/java/org/apache/rocketmq/broker/transaction/queue/TransactionalMessageServiceImpl.java
index 1f5e01efa4..74df47a088 100644
--- a/broker/src/main/java/org/apache/rocketmq/broker/transaction/queue/TransactionalMessageServiceImpl.java
+++ b/broker/src/main/java/org/apache/rocketmq/broker/transaction/queue/TransactionalMessageServiceImpl.java
@@ -164,7 +164,7 @@ public class TransactionalMessageServiceImpl implements TransactionalMessageServ
break;
}
if (removeMap.containsKey(i)) {
- log.info("Half offset {} has been committed/rolled back", i);
+ log.debug("Half offset {} has been committed/rolled back", i);
Long removedOpOffset = removeMap.remove(i);
doneOpOffset.add(removedOpOffset);
} else {
diff --git a/broker/src/test/java/org/apache/rocketmq/broker/BrokerOuterAPITest.java b/broker/src/test/java/org/apache/rocketmq/broker/BrokerOuterAPITest.java
index 68d58ef440..9ea1eeee31 100644
--- a/broker/src/test/java/org/apache/rocketmq/broker/BrokerOuterAPITest.java
+++ b/broker/src/test/java/org/apache/rocketmq/broker/BrokerOuterAPITest.java
@@ -124,7 +124,7 @@ public class BrokerOuterAPITest {
boolean success = Iterables.any(booleanList,
new Predicate() {
public boolean apply(Boolean input) {
- return input ? true : false;
+ return input;
}
});
diff --git a/client/pom.xml b/client/pom.xml
index c775ee8fae..164082c9b2 100644
--- a/client/pom.xml
+++ b/client/pom.xml
@@ -19,7 +19,7 @@
org.apache.rocketmq
rocketmq-all
- 4.8.0-SNAPSHOT
+ 4.8.1-SNAPSHOT
4.0.0
@@ -47,6 +47,18 @@
org.apache.commons
commons-lang3
+
+ io.opentracing
+ opentracing-api
+ 0.33.0
+ provided
+
+
+ io.opentracing
+ opentracing-mock
+ 0.33.0
+ test
+
org.apache.logging.log4j
log4j-core
diff --git a/client/src/main/java/org/apache/rocketmq/client/ClientConfig.java b/client/src/main/java/org/apache/rocketmq/client/ClientConfig.java
index d0ae5e1b83..3ab214b8db 100644
--- a/client/src/main/java/org/apache/rocketmq/client/ClientConfig.java
+++ b/client/src/main/java/org/apache/rocketmq/client/ClientConfig.java
@@ -94,7 +94,7 @@ public class ClientConfig {
public void changeInstanceNameToPID() {
if (this.instanceName.equals("DEFAULT")) {
- this.instanceName = String.valueOf(UtilAll.getPid());
+ this.instanceName = UtilAll.getPid() + "#" + System.nanoTime();
}
}
@@ -178,8 +178,8 @@ public class ClientConfig {
}
public String getNamesrvAddr() {
- if (StringUtils.isNotEmpty(namesrvAddr) && NameServerAddressUtils.NAMESRV_ENDPOINT_PATTERN.matcher(namesrvAddr.trim()).matches()) {
- return namesrvAddr.substring(NameServerAddressUtils.ENDPOINT_PREFIX.length());
+ if (StringUtils.isNotEmpty(namesrvAddr) && NameServerAddressUtils.validateInstanceEndpoint(namesrvAddr.trim())) {
+ return NameServerAddressUtils.getNameSrvAddrFromNamesrvEndpoint(namesrvAddr);
}
return namesrvAddr;
}
diff --git a/client/src/main/java/org/apache/rocketmq/client/common/ThreadLocalIndex.java b/client/src/main/java/org/apache/rocketmq/client/common/ThreadLocalIndex.java
index ab223c3eca..c0b04caea1 100644
--- a/client/src/main/java/org/apache/rocketmq/client/common/ThreadLocalIndex.java
+++ b/client/src/main/java/org/apache/rocketmq/client/common/ThreadLocalIndex.java
@@ -23,19 +23,14 @@ public class ThreadLocalIndex {
private final ThreadLocal threadLocalIndex = new ThreadLocal();
private final Random random = new Random();
- public int getAndIncrement() {
+ public int incrementAndGet() {
Integer index = this.threadLocalIndex.get();
if (null == index) {
index = Math.abs(random.nextInt());
- if (index < 0)
- index = 0;
this.threadLocalIndex.set(index);
}
index = Math.abs(index + 1);
- if (index < 0)
- index = 0;
-
this.threadLocalIndex.set(index);
return index;
}
diff --git a/client/src/main/java/org/apache/rocketmq/client/consumer/rebalance/AllocateMessageQueueByMachineRoom.java b/client/src/main/java/org/apache/rocketmq/client/consumer/rebalance/AllocateMessageQueueByMachineRoom.java
index 37568317cb..31f4e3522e 100644
--- a/client/src/main/java/org/apache/rocketmq/client/consumer/rebalance/AllocateMessageQueueByMachineRoom.java
+++ b/client/src/main/java/org/apache/rocketmq/client/consumer/rebalance/AllocateMessageQueueByMachineRoom.java
@@ -49,7 +49,7 @@ public class AllocateMessageQueueByMachineRoom implements AllocateMessageQueueSt
int startIndex = mod * currentIndex;
int endIndex = startIndex + mod;
for (int i = startIndex; i < endIndex; i++) {
- result.add(mqAll.get(i));
+ result.add(premqAll.get(i));
}
if (rem > currentIndex) {
result.add(premqAll.get(currentIndex + mod * cidAll.size()));
diff --git a/client/src/main/java/org/apache/rocketmq/client/hook/EndTransactionContext.java b/client/src/main/java/org/apache/rocketmq/client/hook/EndTransactionContext.java
new file mode 100644
index 0000000000..5271ade82b
--- /dev/null
+++ b/client/src/main/java/org/apache/rocketmq/client/hook/EndTransactionContext.java
@@ -0,0 +1,86 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.rocketmq.client.hook;
+
+import org.apache.rocketmq.client.producer.LocalTransactionState;
+import org.apache.rocketmq.common.message.Message;
+
+public class EndTransactionContext {
+ private String producerGroup;
+ private Message message;
+ private String brokerAddr;
+ private String msgId;
+ private String transactionId;
+ private LocalTransactionState transactionState;
+ private boolean fromTransactionCheck;
+
+ 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 String getBrokerAddr() {
+ return brokerAddr;
+ }
+
+ public void setBrokerAddr(String brokerAddr) {
+ this.brokerAddr = brokerAddr;
+ }
+
+ public String getMsgId() {
+ return msgId;
+ }
+
+ public void setMsgId(String msgId) {
+ this.msgId = msgId;
+ }
+
+ public String getTransactionId() {
+ return transactionId;
+ }
+
+ public void setTransactionId(String transactionId) {
+ this.transactionId = transactionId;
+ }
+
+ public LocalTransactionState getTransactionState() {
+ return transactionState;
+ }
+
+ public void setTransactionState(LocalTransactionState transactionState) {
+ this.transactionState = transactionState;
+ }
+
+ public boolean isFromTransactionCheck() {
+ return fromTransactionCheck;
+ }
+
+ public void setFromTransactionCheck(boolean fromTransactionCheck) {
+ this.fromTransactionCheck = fromTransactionCheck;
+ }
+}
diff --git a/client/src/main/java/org/apache/rocketmq/client/hook/EndTransactionHook.java b/client/src/main/java/org/apache/rocketmq/client/hook/EndTransactionHook.java
new file mode 100644
index 0000000000..834cb27312
--- /dev/null
+++ b/client/src/main/java/org/apache/rocketmq/client/hook/EndTransactionHook.java
@@ -0,0 +1,23 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.rocketmq.client.hook;
+
+public interface EndTransactionHook {
+ String hookName();
+
+ void endTransaction(final EndTransactionContext context);
+}
diff --git a/client/src/main/java/org/apache/rocketmq/client/impl/ClientRemotingProcessor.java b/client/src/main/java/org/apache/rocketmq/client/impl/ClientRemotingProcessor.java
index 3ef60af179..a541b2d379 100644
--- a/client/src/main/java/org/apache/rocketmq/client/impl/ClientRemotingProcessor.java
+++ b/client/src/main/java/org/apache/rocketmq/client/impl/ClientRemotingProcessor.java
@@ -282,8 +282,6 @@ public class ClientRemotingProcessor extends AsyncNettyRequestProcessor implemen
if (requestResponseFuture.getRequestCallback() != null) {
requestResponseFuture.getRequestCallback().onSuccess(replyMsg);
- } else {
- requestResponseFuture.putResponseMessage(replyMsg);
}
} else {
String bornHost = replyMsg.getBornHostString();
diff --git a/client/src/main/java/org/apache/rocketmq/client/impl/MQClientAPIImpl.java b/client/src/main/java/org/apache/rocketmq/client/impl/MQClientAPIImpl.java
index 7a4d556541..63b2045d1d 100644
--- a/client/src/main/java/org/apache/rocketmq/client/impl/MQClientAPIImpl.java
+++ b/client/src/main/java/org/apache/rocketmq/client/impl/MQClientAPIImpl.java
@@ -1467,10 +1467,11 @@ public class MQClientAPIImpl {
throw new MQClientException(response.getCode(), response.getRemark());
}
- public void deleteSubscriptionGroup(final String addr, final String groupName, final long timeoutMillis)
+ public void deleteSubscriptionGroup(final String addr, final String groupName, final boolean removeOffset, final long timeoutMillis)
throws RemotingException, MQBrokerException, InterruptedException, MQClientException {
DeleteSubscriptionGroupRequestHeader requestHeader = new DeleteSubscriptionGroupRequestHeader();
requestHeader.setGroupName(groupName);
+ requestHeader.setRemoveOffset(removeOffset);
RemotingCommand request = RemotingCommand.createRequestCommand(RequestCode.DELETE_SUBSCRIPTIONGROUP, requestHeader);
RemotingCommand response = this.remotingClient.invokeSync(MixAll.brokerVIPChannel(this.clientConfig.isVipChannelEnabled(), addr),
diff --git a/client/src/main/java/org/apache/rocketmq/client/impl/consumer/AssignedMessageQueue.java b/client/src/main/java/org/apache/rocketmq/client/impl/consumer/AssignedMessageQueue.java
index fad0b4f1b5..4d18a9be1b 100644
--- a/client/src/main/java/org/apache/rocketmq/client/impl/consumer/AssignedMessageQueue.java
+++ b/client/src/main/java/org/apache/rocketmq/client/impl/consumer/AssignedMessageQueue.java
@@ -83,9 +83,12 @@ public class AssignedMessageQueue {
return -1;
}
- public void updatePullOffset(MessageQueue messageQueue, long offset) {
+ public void updatePullOffset(MessageQueue messageQueue, long offset, ProcessQueue processQueue) {
MessageQueueState messageQueueState = assignedMessageQueueState.get(messageQueue);
if (messageQueueState != null) {
+ if (messageQueueState.getProcessQueue() != processQueue) {
+ return;
+ }
messageQueueState.setPullOffset(offset);
}
}
diff --git a/client/src/main/java/org/apache/rocketmq/client/impl/consumer/ConsumeMessageOrderlyService.java b/client/src/main/java/org/apache/rocketmq/client/impl/consumer/ConsumeMessageOrderlyService.java
index a171098181..130effad9e 100644
--- a/client/src/main/java/org/apache/rocketmq/client/impl/consumer/ConsumeMessageOrderlyService.java
+++ b/client/src/main/java/org/apache/rocketmq/client/impl/consumer/ConsumeMessageOrderlyService.java
@@ -478,7 +478,7 @@ public class ConsumeMessageOrderlyService implements ConsumeMessageService {
ConsumeReturnType returnType = ConsumeReturnType.SUCCESS;
boolean hasException = false;
try {
- this.processQueue.getLockConsume().lock();
+ this.processQueue.getConsumeLock().lock();
if (this.processQueue.isDropped()) {
log.warn("consumeMessage, the message queue not be able to consume, because it's dropped. {}",
this.messageQueue);
@@ -494,7 +494,7 @@ public class ConsumeMessageOrderlyService implements ConsumeMessageService {
messageQueue);
hasException = true;
} finally {
- this.processQueue.getLockConsume().unlock();
+ this.processQueue.getConsumeLock().unlock();
}
if (null == status
diff --git a/client/src/main/java/org/apache/rocketmq/client/impl/consumer/DefaultLitePullConsumerImpl.java b/client/src/main/java/org/apache/rocketmq/client/impl/consumer/DefaultLitePullConsumerImpl.java
index 676c03cef4..280de46ff2 100644
--- a/client/src/main/java/org/apache/rocketmq/client/impl/consumer/DefaultLitePullConsumerImpl.java
+++ b/client/src/main/java/org/apache/rocketmq/client/impl/consumer/DefaultLitePullConsumerImpl.java
@@ -432,8 +432,7 @@ public class DefaultLitePullConsumerImpl implements MQConsumerInner {
throw new IllegalArgumentException("Topic can not be null or empty.");
}
setSubscriptionType(SubscriptionType.SUBSCRIBE);
- SubscriptionData subscriptionData = FilterAPI.buildSubscriptionData(defaultLitePullConsumer.getConsumerGroup(),
- topic, subExpression);
+ SubscriptionData subscriptionData = FilterAPI.buildSubscriptionData(topic, subExpression);
this.rebalanceImpl.getSubscriptionInner().put(topic, subscriptionData);
this.defaultLitePullConsumer.setMessageQueueListener(new MessageQueueListenerImpl());
assignedMessageQueue.setRebalanceImpl(this.rebalanceImpl);
@@ -613,9 +612,9 @@ public class DefaultLitePullConsumerImpl implements MQConsumerInner {
}
}
- private void updatePullOffset(MessageQueue messageQueue, long nextPullOffset) {
+ private void updatePullOffset(MessageQueue messageQueue, long nextPullOffset, ProcessQueue processQueue) {
if (assignedMessageQueue.getSeekOffset(messageQueue) == -1) {
- assignedMessageQueue.updatePullOffset(messageQueue, nextPullOffset);
+ assignedMessageQueue.updatePullOffset(messageQueue, nextPullOffset, processQueue);
}
}
@@ -741,6 +740,9 @@ public class DefaultLitePullConsumerImpl implements MQConsumerInner {
}
long offset = nextPullOffset(messageQueue);
+ if (this.isCancelled() || processQueue.isDropped()) {
+ return;
+ }
long pullDelayTimeMills = 0;
try {
SubscriptionData subscriptionData;
@@ -749,12 +751,13 @@ public class DefaultLitePullConsumerImpl implements MQConsumerInner {
subscriptionData = rebalanceImpl.getSubscriptionInner().get(topic);
} else {
String topic = this.messageQueue.getTopic();
- subscriptionData = FilterAPI.buildSubscriptionData(defaultLitePullConsumer.getConsumerGroup(),
- topic, SubscriptionData.SUB_ALL);
+ subscriptionData = FilterAPI.buildSubscriptionData(topic, SubscriptionData.SUB_ALL);
}
PullResult pullResult = pull(messageQueue, subscriptionData, offset, defaultLitePullConsumer.getPullBatchSize());
-
+ if (this.isCancelled() || processQueue.isDropped()) {
+ return;
+ }
switch (pullResult.getPullStatus()) {
case FOUND:
final Object objLock = messageQueueLock.fetchLockObject(messageQueue);
@@ -771,7 +774,7 @@ public class DefaultLitePullConsumerImpl implements MQConsumerInner {
default:
break;
}
- updatePullOffset(messageQueue, pullResult.getNextBeginOffset());
+ updatePullOffset(messageQueue, pullResult.getNextBeginOffset(), processQueue);
} catch (Throwable e) {
pullDelayTimeMills = pullTimeDelayMillsWhenException;
log.error("An error occurred in pull message process.", e);
diff --git a/client/src/main/java/org/apache/rocketmq/client/impl/consumer/DefaultMQPullConsumerImpl.java b/client/src/main/java/org/apache/rocketmq/client/impl/consumer/DefaultMQPullConsumerImpl.java
index afd72a0800..eed5fa43f0 100644
--- a/client/src/main/java/org/apache/rocketmq/client/impl/consumer/DefaultMQPullConsumerImpl.java
+++ b/client/src/main/java/org/apache/rocketmq/client/impl/consumer/DefaultMQPullConsumerImpl.java
@@ -205,8 +205,7 @@ public class DefaultMQPullConsumerImpl implements MQConsumerInner {
}
try {
- return FilterAPI.buildSubscriptionData(this.defaultMQPullConsumer.getConsumerGroup(),
- mq.getTopic(), subExpression);
+ return FilterAPI.buildSubscriptionData(mq.getTopic(), subExpression);
} catch (Exception e) {
throw new MQClientException("parse subscription error", e);
}
@@ -301,8 +300,7 @@ public class DefaultMQPullConsumerImpl implements MQConsumerInner {
public void subscriptionAutomatically(final String topic) {
if (!this.rebalanceImpl.getSubscriptionInner().containsKey(topic)) {
try {
- SubscriptionData subscriptionData = FilterAPI.buildSubscriptionData(this.defaultMQPullConsumer.getConsumerGroup(),
- topic, SubscriptionData.SUB_ALL);
+ SubscriptionData subscriptionData = FilterAPI.buildSubscriptionData(topic, SubscriptionData.SUB_ALL);
this.rebalanceImpl.subscriptionInner.putIfAbsent(topic, subscriptionData);
} catch (Exception ignore) {
}
@@ -365,7 +363,7 @@ public class DefaultMQPullConsumerImpl implements MQConsumerInner {
for (String t : topics) {
SubscriptionData ms = null;
try {
- ms = FilterAPI.buildSubscriptionData(this.groupName(), t, SubscriptionData.SUB_ALL);
+ ms = FilterAPI.buildSubscriptionData(t, SubscriptionData.SUB_ALL);
} catch (Exception e) {
log.error("parse subscription error", e);
}
@@ -742,8 +740,7 @@ public class DefaultMQPullConsumerImpl implements MQConsumerInner {
Set registerTopics = this.defaultMQPullConsumer.getRegisterTopics();
if (registerTopics != null) {
for (final String topic : registerTopics) {
- SubscriptionData subscriptionData = FilterAPI.buildSubscriptionData(this.defaultMQPullConsumer.getConsumerGroup(),
- topic, SubscriptionData.SUB_ALL);
+ SubscriptionData subscriptionData = FilterAPI.buildSubscriptionData(topic, SubscriptionData.SUB_ALL);
this.rebalanceImpl.getSubscriptionInner().put(topic, subscriptionData);
}
}
diff --git a/client/src/main/java/org/apache/rocketmq/client/impl/consumer/DefaultMQPushConsumerImpl.java b/client/src/main/java/org/apache/rocketmq/client/impl/consumer/DefaultMQPushConsumerImpl.java
index a9dbc3157b..e08f780030 100644
--- a/client/src/main/java/org/apache/rocketmq/client/impl/consumer/DefaultMQPushConsumerImpl.java
+++ b/client/src/main/java/org/apache/rocketmq/client/impl/consumer/DefaultMQPushConsumerImpl.java
@@ -827,8 +827,7 @@ public class DefaultMQPushConsumerImpl implements MQConsumerInner {
for (final Map.Entry entry : sub.entrySet()) {
final String topic = entry.getKey();
final String subString = entry.getValue();
- SubscriptionData subscriptionData = FilterAPI.buildSubscriptionData(this.defaultMQPushConsumer.getConsumerGroup(),
- topic, subString);
+ SubscriptionData subscriptionData = FilterAPI.buildSubscriptionData(topic, subString);
this.rebalanceImpl.getSubscriptionInner().put(topic, subscriptionData);
}
}
@@ -842,8 +841,7 @@ public class DefaultMQPushConsumerImpl implements MQConsumerInner {
break;
case CLUSTERING:
final String retryTopic = MixAll.getRetryTopic(this.defaultMQPushConsumer.getConsumerGroup());
- SubscriptionData subscriptionData = FilterAPI.buildSubscriptionData(this.defaultMQPushConsumer.getConsumerGroup(),
- retryTopic, SubscriptionData.SUB_ALL);
+ SubscriptionData subscriptionData = FilterAPI.buildSubscriptionData(retryTopic, SubscriptionData.SUB_ALL);
this.rebalanceImpl.getSubscriptionInner().put(retryTopic, subscriptionData);
break;
default:
@@ -874,8 +872,7 @@ public class DefaultMQPushConsumerImpl implements MQConsumerInner {
public void subscribe(String topic, String subExpression) throws MQClientException {
try {
- SubscriptionData subscriptionData = FilterAPI.buildSubscriptionData(this.defaultMQPushConsumer.getConsumerGroup(),
- topic, subExpression);
+ SubscriptionData subscriptionData = FilterAPI.buildSubscriptionData(topic, subExpression);
this.rebalanceImpl.getSubscriptionInner().put(topic, subscriptionData);
if (this.mQClientFactory != null) {
this.mQClientFactory.sendHeartbeatToAllBrokerWithLock();
@@ -887,8 +884,7 @@ public class DefaultMQPushConsumerImpl implements MQConsumerInner {
public void subscribe(String topic, String fullClassName, String filterClassSource) throws MQClientException {
try {
- SubscriptionData subscriptionData = FilterAPI.buildSubscriptionData(this.defaultMQPushConsumer.getConsumerGroup(),
- topic, "*");
+ SubscriptionData subscriptionData = FilterAPI.buildSubscriptionData(topic, "*");
subscriptionData.setSubString(fullClassName);
subscriptionData.setClassFilterMode(true);
subscriptionData.setFilterClassSource(filterClassSource);
diff --git a/client/src/main/java/org/apache/rocketmq/client/impl/consumer/ProcessQueue.java b/client/src/main/java/org/apache/rocketmq/client/impl/consumer/ProcessQueue.java
index 4b9ea62c33..21798d8c6e 100644
--- a/client/src/main/java/org/apache/rocketmq/client/impl/consumer/ProcessQueue.java
+++ b/client/src/main/java/org/apache/rocketmq/client/impl/consumer/ProcessQueue.java
@@ -44,11 +44,11 @@ public class ProcessQueue {
public final static long REBALANCE_LOCK_INTERVAL = Long.parseLong(System.getProperty("rocketmq.client.rebalance.lockInterval", "20000"));
private final static long PULL_MAX_IDLE_TIME = Long.parseLong(System.getProperty("rocketmq.client.pull.pullMaxIdleTime", "120000"));
private final InternalLogger log = ClientLogger.getLog();
- private final ReadWriteLock lockTreeMap = new ReentrantReadWriteLock();
+ private final ReadWriteLock treeMapLock = new ReentrantReadWriteLock();
private final TreeMap msgTreeMap = new TreeMap();
private final AtomicLong msgCount = new AtomicLong();
private final AtomicLong msgSize = new AtomicLong();
- private final Lock lockConsume = new ReentrantLock();
+ private final Lock consumeLock = new ReentrantLock();
/**
* A subset of msgTreeMap, will only be used when orderly consume
*/
@@ -83,7 +83,7 @@ public class ProcessQueue {
for (int i = 0; i < loop; i++) {
MessageExt msg = null;
try {
- this.lockTreeMap.readLock().lockInterruptibly();
+ this.treeMapLock.readLock().lockInterruptibly();
try {
if (!msgTreeMap.isEmpty() && System.currentTimeMillis() - Long.parseLong(MessageAccessor.getConsumeStartTimeStamp(msgTreeMap.firstEntry().getValue())) > pushConsumer.getConsumeTimeout() * 60 * 1000) {
msg = msgTreeMap.firstEntry().getValue();
@@ -92,7 +92,7 @@ public class ProcessQueue {
break;
}
} finally {
- this.lockTreeMap.readLock().unlock();
+ this.treeMapLock.readLock().unlock();
}
} catch (InterruptedException e) {
log.error("getExpiredMsg exception", e);
@@ -103,7 +103,7 @@ public class ProcessQueue {
pushConsumer.sendMessageBack(msg, 3);
log.info("send expire msg back. topic={}, msgId={}, storeHost={}, queueId={}, queueOffset={}", msg.getTopic(), msg.getMsgId(), msg.getStoreHost(), msg.getQueueId(), msg.getQueueOffset());
try {
- this.lockTreeMap.writeLock().lockInterruptibly();
+ this.treeMapLock.writeLock().lockInterruptibly();
try {
if (!msgTreeMap.isEmpty() && msg.getQueueOffset() == msgTreeMap.firstKey()) {
try {
@@ -113,7 +113,7 @@ public class ProcessQueue {
}
}
} finally {
- this.lockTreeMap.writeLock().unlock();
+ this.treeMapLock.writeLock().unlock();
}
} catch (InterruptedException e) {
log.error("getExpiredMsg exception", e);
@@ -127,7 +127,7 @@ public class ProcessQueue {
public boolean putMessage(final List msgs) {
boolean dispatchToConsume = false;
try {
- this.lockTreeMap.writeLock().lockInterruptibly();
+ this.treeMapLock.writeLock().lockInterruptibly();
try {
int validMsgCnt = 0;
for (MessageExt msg : msgs) {
@@ -156,7 +156,7 @@ public class ProcessQueue {
}
}
} finally {
- this.lockTreeMap.writeLock().unlock();
+ this.treeMapLock.writeLock().unlock();
}
} catch (InterruptedException e) {
log.error("putMessage exception", e);
@@ -167,13 +167,13 @@ public class ProcessQueue {
public long getMaxSpan() {
try {
- this.lockTreeMap.readLock().lockInterruptibly();
+ this.treeMapLock.readLock().lockInterruptibly();
try {
if (!this.msgTreeMap.isEmpty()) {
return this.msgTreeMap.lastKey() - this.msgTreeMap.firstKey();
}
} finally {
- this.lockTreeMap.readLock().unlock();
+ this.treeMapLock.readLock().unlock();
}
} catch (InterruptedException e) {
log.error("getMaxSpan exception", e);
@@ -186,7 +186,7 @@ public class ProcessQueue {
long result = -1;
final long now = System.currentTimeMillis();
try {
- this.lockTreeMap.writeLock().lockInterruptibly();
+ this.treeMapLock.writeLock().lockInterruptibly();
this.lastConsumeTimestamp = now;
try {
if (!msgTreeMap.isEmpty()) {
@@ -206,7 +206,7 @@ public class ProcessQueue {
}
}
} finally {
- this.lockTreeMap.writeLock().unlock();
+ this.treeMapLock.writeLock().unlock();
}
} catch (Throwable t) {
log.error("removeMessage exception", t);
@@ -245,12 +245,12 @@ public class ProcessQueue {
public void rollback() {
try {
- this.lockTreeMap.writeLock().lockInterruptibly();
+ this.treeMapLock.writeLock().lockInterruptibly();
try {
this.msgTreeMap.putAll(this.consumingMsgOrderlyTreeMap);
this.consumingMsgOrderlyTreeMap.clear();
} finally {
- this.lockTreeMap.writeLock().unlock();
+ this.treeMapLock.writeLock().unlock();
}
} catch (InterruptedException e) {
log.error("rollback exception", e);
@@ -259,7 +259,7 @@ public class ProcessQueue {
public long commit() {
try {
- this.lockTreeMap.writeLock().lockInterruptibly();
+ this.treeMapLock.writeLock().lockInterruptibly();
try {
Long offset = this.consumingMsgOrderlyTreeMap.lastKey();
msgCount.addAndGet(0 - this.consumingMsgOrderlyTreeMap.size());
@@ -271,7 +271,7 @@ public class ProcessQueue {
return offset + 1;
}
} finally {
- this.lockTreeMap.writeLock().unlock();
+ this.treeMapLock.writeLock().unlock();
}
} catch (InterruptedException e) {
log.error("commit exception", e);
@@ -282,14 +282,14 @@ public class ProcessQueue {
public void makeMessageToConsumeAgain(List msgs) {
try {
- this.lockTreeMap.writeLock().lockInterruptibly();
+ this.treeMapLock.writeLock().lockInterruptibly();
try {
for (MessageExt msg : msgs) {
this.consumingMsgOrderlyTreeMap.remove(msg.getQueueOffset());
this.msgTreeMap.put(msg.getQueueOffset(), msg);
}
} finally {
- this.lockTreeMap.writeLock().unlock();
+ this.treeMapLock.writeLock().unlock();
}
} catch (InterruptedException e) {
log.error("makeMessageToCosumeAgain exception", e);
@@ -300,7 +300,7 @@ public class ProcessQueue {
List result = new ArrayList(batchSize);
final long now = System.currentTimeMillis();
try {
- this.lockTreeMap.writeLock().lockInterruptibly();
+ this.treeMapLock.writeLock().lockInterruptibly();
this.lastConsumeTimestamp = now;
try {
if (!this.msgTreeMap.isEmpty()) {
@@ -319,7 +319,7 @@ public class ProcessQueue {
consuming = false;
}
} finally {
- this.lockTreeMap.writeLock().unlock();
+ this.treeMapLock.writeLock().unlock();
}
} catch (InterruptedException e) {
log.error("take Messages exception", e);
@@ -330,11 +330,11 @@ public class ProcessQueue {
public boolean hasTempMessage() {
try {
- this.lockTreeMap.readLock().lockInterruptibly();
+ this.treeMapLock.readLock().lockInterruptibly();
try {
return !this.msgTreeMap.isEmpty();
} finally {
- this.lockTreeMap.readLock().unlock();
+ this.treeMapLock.readLock().unlock();
}
} catch (InterruptedException e) {
}
@@ -344,7 +344,7 @@ public class ProcessQueue {
public void clear() {
try {
- this.lockTreeMap.writeLock().lockInterruptibly();
+ this.treeMapLock.writeLock().lockInterruptibly();
try {
this.msgTreeMap.clear();
this.consumingMsgOrderlyTreeMap.clear();
@@ -352,7 +352,7 @@ public class ProcessQueue {
this.msgSize.set(0);
this.queueOffsetMax = 0L;
} finally {
- this.lockTreeMap.writeLock().unlock();
+ this.treeMapLock.writeLock().unlock();
}
} catch (InterruptedException e) {
log.error("rollback exception", e);
@@ -367,8 +367,8 @@ public class ProcessQueue {
this.lastLockTimestamp = lastLockTimestamp;
}
- public Lock getLockConsume() {
- return lockConsume;
+ public Lock getConsumeLock() {
+ return consumeLock;
}
public long getLastPullTimestamp() {
@@ -397,7 +397,7 @@ public class ProcessQueue {
public void fillProcessQueueInfo(final ProcessQueueInfo info) {
try {
- this.lockTreeMap.readLock().lockInterruptibly();
+ this.treeMapLock.readLock().lockInterruptibly();
if (!this.msgTreeMap.isEmpty()) {
info.setCachedMsgMinOffset(this.msgTreeMap.firstKey());
@@ -421,7 +421,7 @@ public class ProcessQueue {
info.setLastConsumeTimestamp(this.lastConsumeTimestamp);
} catch (Exception e) {
} finally {
- this.lockTreeMap.readLock().unlock();
+ this.treeMapLock.readLock().unlock();
}
}
diff --git a/client/src/main/java/org/apache/rocketmq/client/impl/consumer/RebalancePushImpl.java b/client/src/main/java/org/apache/rocketmq/client/impl/consumer/RebalancePushImpl.java
index e5166f35b5..9582391622 100644
--- a/client/src/main/java/org/apache/rocketmq/client/impl/consumer/RebalancePushImpl.java
+++ b/client/src/main/java/org/apache/rocketmq/client/impl/consumer/RebalancePushImpl.java
@@ -88,11 +88,11 @@ public class RebalancePushImpl extends RebalanceImpl {
if (this.defaultMQPushConsumerImpl.isConsumeOrderly()
&& MessageModel.CLUSTERING.equals(this.defaultMQPushConsumerImpl.messageModel())) {
try {
- if (pq.getLockConsume().tryLock(1000, TimeUnit.MILLISECONDS)) {
+ if (pq.getConsumeLock().tryLock(1000, TimeUnit.MILLISECONDS)) {
try {
return this.unlockDelay(mq, pq);
} finally {
- pq.getLockConsume().unlock();
+ pq.getConsumeLock().unlock();
}
} else {
log.warn("[WRONG]mq is consuming, so can not unlock it, {}. maybe hanged for a while, {}",
diff --git a/client/src/main/java/org/apache/rocketmq/client/impl/factory/MQClientInstance.java b/client/src/main/java/org/apache/rocketmq/client/impl/factory/MQClientInstance.java
index 48cc18851d..81e6d8468e 100644
--- a/client/src/main/java/org/apache/rocketmq/client/impl/factory/MQClientInstance.java
+++ b/client/src/main/java/org/apache/rocketmq/client/impl/factory/MQClientInstance.java
@@ -1043,6 +1043,11 @@ public class MQClientInstance {
slave = brokerId != MixAll.MASTER_ID;
found = brokerAddr != null;
+ if (!found && slave) {
+ brokerAddr = map.get(brokerId + 1);
+ found = brokerAddr != null;
+ }
+
if (!found && !onlyThisBroker) {
Entry entry = map.entrySet().iterator().next();
brokerAddr = entry.getValue();
@@ -1100,7 +1105,7 @@ public class MQClientInstance {
return null;
}
- public void resetOffset(String topic, String group, Map offsetTable) {
+ public synchronized void resetOffset(String topic, String group, Map offsetTable) {
DefaultMQPushConsumerImpl consumer = null;
try {
MQConsumerInner impl = this.consumerTable.get(group);
@@ -1209,6 +1214,9 @@ public class MQClientInstance {
public ConsumerRunningInfo consumerRunningInfo(final String consumerGroup) {
MQConsumerInner mqConsumerInner = this.consumerTable.get(consumerGroup);
+ if (mqConsumerInner == null) {
+ return null;
+ }
ConsumerRunningInfo consumerRunningInfo = mqConsumerInner.consumerRunningInfo();
diff --git a/client/src/main/java/org/apache/rocketmq/client/impl/producer/DefaultMQProducerImpl.java b/client/src/main/java/org/apache/rocketmq/client/impl/producer/DefaultMQProducerImpl.java
index 2f9146d910..fac3ed3561 100644
--- a/client/src/main/java/org/apache/rocketmq/client/impl/producer/DefaultMQProducerImpl.java
+++ b/client/src/main/java/org/apache/rocketmq/client/impl/producer/DefaultMQProducerImpl.java
@@ -44,6 +44,8 @@ import org.apache.rocketmq.client.exception.MQClientException;
import org.apache.rocketmq.client.exception.RequestTimeoutException;
import org.apache.rocketmq.client.hook.CheckForbiddenContext;
import org.apache.rocketmq.client.hook.CheckForbiddenHook;
+import org.apache.rocketmq.client.hook.EndTransactionContext;
+import org.apache.rocketmq.client.hook.EndTransactionHook;
import org.apache.rocketmq.client.hook.SendMessageContext;
import org.apache.rocketmq.client.hook.SendMessageHook;
import org.apache.rocketmq.client.impl.CommunicationMode;
@@ -101,6 +103,7 @@ public class DefaultMQProducerImpl implements MQProducerInner {
private final ConcurrentMap topicPublishInfoTable =
new ConcurrentHashMap();
private final ArrayList sendMessageHookList = new ArrayList();
+ private final ArrayList endTransactionHookList = new ArrayList();
private final RPCHook rpcHook;
private final BlockingQueue asyncSenderThreadPoolQueue;
private final ExecutorService defaultAsyncSenderExecutor;
@@ -171,6 +174,11 @@ public class DefaultMQProducerImpl implements MQProducerInner {
log.info("register sendMessage Hook, {}", hook.hookName());
}
+ public void registerEndTransactionHook(final EndTransactionHook hook) {
+ this.endTransactionHookList.add(hook);
+ log.info("register endTransaction Hook, {}", hook.hookName());
+ }
+
public void start() throws MQClientException {
this.start(true);
}
@@ -386,6 +394,7 @@ public class DefaultMQProducerImpl implements MQProducerInner {
if (exception != null) {
remark = "checkLocalTransactionState Exception: " + RemotingHelper.exceptionSimpleDesc(exception);
}
+ doExecuteEndTransactionHook(msg, uniqueKey, brokerAddr, localTransactionState, true);
try {
DefaultMQProducerImpl.this.mQClientFactory.getMQClientAPIImpl().endTransactionOneway(brokerAddr, thisHeader, remark,
@@ -967,6 +976,36 @@ public class DefaultMQProducerImpl implements MQProducerInner {
}
}
+ public boolean hasEndTransactionHook() {
+ return !this.endTransactionHookList.isEmpty();
+ }
+
+ public void executeEndTransactionHook(final EndTransactionContext context) {
+ if (!this.endTransactionHookList.isEmpty()) {
+ for (EndTransactionHook hook : this.endTransactionHookList) {
+ try {
+ hook.endTransaction(context);
+ } catch (Throwable e) {
+ log.warn("failed to executeEndTransactionHook", e);
+ }
+ }
+ }
+ }
+
+ public void doExecuteEndTransactionHook(Message msg, String msgId, String brokerAddr, LocalTransactionState state,
+ boolean fromTransactionCheck) {
+ if (hasEndTransactionHook()) {
+ EndTransactionContext context = new EndTransactionContext();
+ context.setProducerGroup(defaultMQProducer.getProducerGroup());
+ context.setBrokerAddr(brokerAddr);
+ context.setMessage(msg);
+ context.setMsgId(msgId);
+ context.setTransactionId(msg.getTransactionId());
+ context.setTransactionState(state);
+ context.setFromTransactionCheck(fromTransactionCheck);
+ executeEndTransactionHook(context);
+ }
+ }
/**
* DEFAULT ONEWAY -------------------------------------------------------
*/
@@ -1266,7 +1305,7 @@ public class DefaultMQProducerImpl implements MQProducerInner {
}
try {
- this.endTransaction(sendResult, localTransactionState, localException);
+ this.endTransaction(msg, sendResult, localTransactionState, localException);
} catch (Exception e) {
log.warn("local transaction execute " + localTransactionState + ", but end broker transaction failed", e);
}
@@ -1290,6 +1329,7 @@ public class DefaultMQProducerImpl implements MQProducerInner {
}
public void endTransaction(
+ final Message msg,
final SendResult sendResult,
final LocalTransactionState localTransactionState,
final Throwable localException) throws RemotingException, MQBrokerException, InterruptedException, UnknownHostException {
@@ -1318,6 +1358,7 @@ public class DefaultMQProducerImpl implements MQProducerInner {
break;
}
+ doExecuteEndTransactionHook(msg, sendResult.getMsgId(), brokerAddr, localTransactionState, false);
requestHeader.setProducerGroup(this.defaultMQProducer.getProducerGroup());
requestHeader.setTranStateTableOffset(sendResult.getQueueOffset());
requestHeader.setMsgId(sendResult.getMsgId());
diff --git a/client/src/main/java/org/apache/rocketmq/client/impl/producer/TopicPublishInfo.java b/client/src/main/java/org/apache/rocketmq/client/impl/producer/TopicPublishInfo.java
index deb02cff28..2f8337edef 100644
--- a/client/src/main/java/org/apache/rocketmq/client/impl/producer/TopicPublishInfo.java
+++ b/client/src/main/java/org/apache/rocketmq/client/impl/producer/TopicPublishInfo.java
@@ -70,9 +70,9 @@ public class TopicPublishInfo {
if (lastBrokerName == null) {
return selectOneMessageQueue();
} else {
- int index = this.sendWhichQueue.getAndIncrement();
for (int i = 0; i < this.messageQueueList.size(); i++) {
- int pos = Math.abs(index++) % this.messageQueueList.size();
+ int index = this.sendWhichQueue.incrementAndGet();
+ int pos = Math.abs(index) % this.messageQueueList.size();
if (pos < 0)
pos = 0;
MessageQueue mq = this.messageQueueList.get(pos);
@@ -85,7 +85,7 @@ public class TopicPublishInfo {
}
public MessageQueue selectOneMessageQueue() {
- int index = this.sendWhichQueue.getAndIncrement();
+ int index = this.sendWhichQueue.incrementAndGet();
int pos = Math.abs(index) % this.messageQueueList.size();
if (pos < 0)
pos = 0;
diff --git a/client/src/main/java/org/apache/rocketmq/client/latency/LatencyFaultToleranceImpl.java b/client/src/main/java/org/apache/rocketmq/client/latency/LatencyFaultToleranceImpl.java
index 72d43476f8..827d97265f 100644
--- a/client/src/main/java/org/apache/rocketmq/client/latency/LatencyFaultToleranceImpl.java
+++ b/client/src/main/java/org/apache/rocketmq/client/latency/LatencyFaultToleranceImpl.java
@@ -80,7 +80,7 @@ public class LatencyFaultToleranceImpl implements LatencyFaultTolerance
if (half <= 0) {
return tmpList.get(0).getName();
} else {
- final int i = this.whichItemWorst.getAndIncrement() % half;
+ final int i = this.whichItemWorst.incrementAndGet() % half;
return tmpList.get(i).getName();
}
}
diff --git a/client/src/main/java/org/apache/rocketmq/client/latency/MQFaultStrategy.java b/client/src/main/java/org/apache/rocketmq/client/latency/MQFaultStrategy.java
index 651d043a6e..ea3d07e6d0 100644
--- a/client/src/main/java/org/apache/rocketmq/client/latency/MQFaultStrategy.java
+++ b/client/src/main/java/org/apache/rocketmq/client/latency/MQFaultStrategy.java
@@ -58,7 +58,7 @@ public class MQFaultStrategy {
public MessageQueue selectOneMessageQueue(final TopicPublishInfo tpInfo, final String lastBrokerName) {
if (this.sendLatencyFaultEnable) {
try {
- int index = tpInfo.getSendWhichQueue().getAndIncrement();
+ int index = tpInfo.getSendWhichQueue().incrementAndGet();
for (int i = 0; i < tpInfo.getMessageQueueList().size(); i++) {
int pos = Math.abs(index++) % tpInfo.getMessageQueueList().size();
if (pos < 0)
@@ -74,7 +74,7 @@ public class MQFaultStrategy {
final MessageQueue mq = tpInfo.selectOneMessageQueue();
if (notBestBroker != null) {
mq.setBrokerName(notBestBroker);
- mq.setQueueId(tpInfo.getSendWhichQueue().getAndIncrement() % writeQueueNums);
+ mq.setQueueId(tpInfo.getSendWhichQueue().incrementAndGet() % writeQueueNums);
}
return mq;
} else {
diff --git a/client/src/main/java/org/apache/rocketmq/client/producer/DefaultMQProducer.java b/client/src/main/java/org/apache/rocketmq/client/producer/DefaultMQProducer.java
index 24caf14054..1c4a9315a8 100644
--- a/client/src/main/java/org/apache/rocketmq/client/producer/DefaultMQProducer.java
+++ b/client/src/main/java/org/apache/rocketmq/client/producer/DefaultMQProducer.java
@@ -29,6 +29,7 @@ import org.apache.rocketmq.client.impl.producer.DefaultMQProducerImpl;
import org.apache.rocketmq.client.log.ClientLogger;
import org.apache.rocketmq.client.trace.AsyncTraceDispatcher;
import org.apache.rocketmq.client.trace.TraceDispatcher;
+import org.apache.rocketmq.client.trace.hook.EndTransactionTraceHookImpl;
import org.apache.rocketmq.client.trace.hook.SendMessageTraceHookImpl;
import org.apache.rocketmq.common.MixAll;
import org.apache.rocketmq.common.message.Message;
@@ -167,6 +168,8 @@ public class DefaultMQProducer extends ClientConfig implements MQProducer {
traceDispatcher = dispatcher;
this.defaultMQProducerImpl.registerSendMessageHook(
new SendMessageTraceHookImpl(traceDispatcher));
+ this.defaultMQProducerImpl.registerEndTransactionHook(
+ new EndTransactionTraceHookImpl(traceDispatcher));
} catch (Throwable e) {
log.error("system mqtrace hook init failed ,maybe can't send msg trace data");
}
@@ -252,6 +255,8 @@ public class DefaultMQProducer extends ClientConfig implements MQProducer {
traceDispatcher = dispatcher;
this.getDefaultMQProducerImpl().registerSendMessageHook(
new SendMessageTraceHookImpl(traceDispatcher));
+ this.defaultMQProducerImpl.registerEndTransactionHook(
+ new EndTransactionTraceHookImpl(traceDispatcher));
} catch (Throwable e) {
log.error("system mqtrace hook init failed ,maybe can't send msg trace data");
}
@@ -916,24 +921,24 @@ public class DefaultMQProducer extends ClientConfig implements MQProducer {
long timeout) throws MQClientException, RemotingException, MQBrokerException, InterruptedException {
return this.defaultMQProducerImpl.send(batch(msgs), messageQueue, timeout);
}
-
+
@Override
public void send(Collection msgs, SendCallback sendCallback) throws MQClientException, RemotingException, MQBrokerException, InterruptedException {
this.defaultMQProducerImpl.send(batch(msgs), sendCallback);
}
-
+
@Override
public void send(Collection msgs, SendCallback sendCallback,
long timeout) throws MQClientException, RemotingException, MQBrokerException, InterruptedException {
this.defaultMQProducerImpl.send(batch(msgs), sendCallback, timeout);
}
-
+
@Override
public void send(Collection msgs, MessageQueue mq,
SendCallback sendCallback) throws MQClientException, RemotingException, MQBrokerException, InterruptedException {
this.defaultMQProducerImpl.send(batch(msgs), queueWithNamespace(mq), sendCallback);
}
-
+
@Override
public void send(Collection msgs, MessageQueue mq,
SendCallback sendCallback, long timeout) throws MQClientException, RemotingException, MQBrokerException, InterruptedException {
diff --git a/client/src/main/java/org/apache/rocketmq/client/producer/TransactionMQProducer.java b/client/src/main/java/org/apache/rocketmq/client/producer/TransactionMQProducer.java
index 63b512df7d..4eb758df40 100644
--- a/client/src/main/java/org/apache/rocketmq/client/producer/TransactionMQProducer.java
+++ b/client/src/main/java/org/apache/rocketmq/client/producer/TransactionMQProducer.java
@@ -51,6 +51,10 @@ public class TransactionMQProducer extends DefaultMQProducer {
super(namespace, producerGroup, rpcHook);
}
+ public TransactionMQProducer(final String namespace, final String producerGroup, RPCHook rpcHook, boolean enableMsgTrace, final String customizedTraceTopic) {
+ super(namespace, producerGroup, rpcHook, enableMsgTrace, customizedTraceTopic);
+ }
+
@Override
public void start() throws MQClientException {
this.defaultMQProducerImpl.initTransactionEnv();
diff --git a/client/src/main/java/org/apache/rocketmq/client/producer/selector/SelectMessageQueueByHash.java b/client/src/main/java/org/apache/rocketmq/client/producer/selector/SelectMessageQueueByHash.java
index 11e2822b22..ba8ea8b58a 100644
--- a/client/src/main/java/org/apache/rocketmq/client/producer/selector/SelectMessageQueueByHash.java
+++ b/client/src/main/java/org/apache/rocketmq/client/producer/selector/SelectMessageQueueByHash.java
@@ -25,12 +25,10 @@ public class SelectMessageQueueByHash implements MessageQueueSelector {
@Override
public MessageQueue select(List mqs, Message msg, Object arg) {
- int value = arg.hashCode();
+ int value = arg.hashCode() % mqs.size();
if (value < 0) {
value = Math.abs(value);
}
-
- value = value % mqs.size();
return mqs.get(value);
}
}
diff --git a/client/src/main/java/org/apache/rocketmq/client/trace/AsyncTraceDispatcher.java b/client/src/main/java/org/apache/rocketmq/client/trace/AsyncTraceDispatcher.java
index 1af6e60aab..8210b41cd4 100644
--- a/client/src/main/java/org/apache/rocketmq/client/trace/AsyncTraceDispatcher.java
+++ b/client/src/main/java/org/apache/rocketmq/client/trace/AsyncTraceDispatcher.java
@@ -370,7 +370,7 @@ public class AsyncTraceDispatcher implements TraceDispatcher {
@Override
public void onException(Throwable e) {
- log.info("send trace data ,the traceData is " + data);
+ log.error("send trace data failed, the traceData is {}", data, e);
}
};
if (traceBrokerSet.isEmpty()) {
@@ -387,7 +387,7 @@ public class AsyncTraceDispatcher implements TraceDispatcher {
filterMqs.add(queue);
}
}
- int index = sendWhichQueue.getAndIncrement();
+ int index = sendWhichQueue.incrementAndGet();
int pos = Math.abs(index) % filterMqs.size();
if (pos < 0) {
pos = 0;
@@ -398,7 +398,7 @@ public class AsyncTraceDispatcher implements TraceDispatcher {
}
} catch (Exception e) {
- log.info("send trace data,the traceData is" + data);
+ log.error("send trace data failed, the traceData is {}", data, e);
}
}
diff --git a/client/src/main/java/org/apache/rocketmq/client/trace/TraceBean.java b/client/src/main/java/org/apache/rocketmq/client/trace/TraceBean.java
index f93aa38b82..70c147e1eb 100644
--- a/client/src/main/java/org/apache/rocketmq/client/trace/TraceBean.java
+++ b/client/src/main/java/org/apache/rocketmq/client/trace/TraceBean.java
@@ -16,6 +16,7 @@
*/
package org.apache.rocketmq.client.trace;
+import org.apache.rocketmq.client.producer.LocalTransactionState;
import org.apache.rocketmq.common.UtilAll;
import org.apache.rocketmq.common.message.MessageType;
@@ -32,7 +33,9 @@ public class TraceBean {
private int retryTimes;
private int bodyLength;
private MessageType msgType;
-
+ private LocalTransactionState transactionState;
+ private String transactionId;
+ private boolean fromTransactionCheck;
public MessageType getMsgType() {
return msgType;
@@ -141,4 +144,28 @@ public class TraceBean {
public void setBodyLength(int bodyLength) {
this.bodyLength = bodyLength;
}
+
+ public LocalTransactionState getTransactionState() {
+ return transactionState;
+ }
+
+ public void setTransactionState(LocalTransactionState transactionState) {
+ this.transactionState = transactionState;
+ }
+
+ public String getTransactionId() {
+ return transactionId;
+ }
+
+ public void setTransactionId(String transactionId) {
+ this.transactionId = transactionId;
+ }
+
+ public boolean isFromTransactionCheck() {
+ return fromTransactionCheck;
+ }
+
+ public void setFromTransactionCheck(boolean fromTransactionCheck) {
+ this.fromTransactionCheck = fromTransactionCheck;
+ }
}
diff --git a/client/src/main/java/org/apache/rocketmq/client/trace/TraceConstants.java b/client/src/main/java/org/apache/rocketmq/client/trace/TraceConstants.java
index 27622cd302..1ad4b61051 100644
--- a/client/src/main/java/org/apache/rocketmq/client/trace/TraceConstants.java
+++ b/client/src/main/java/org/apache/rocketmq/client/trace/TraceConstants.java
@@ -25,4 +25,20 @@ public class TraceConstants {
public static final char FIELD_SPLITOR = (char) 2;
public static final String TRACE_INSTANCE_NAME = "PID_CLIENT_INNER_TRACE_PRODUCER";
public static final String TRACE_TOPIC_PREFIX = TopicValidator.SYSTEM_TOPIC_PREFIX + "TRACE_DATA_";
+ public static final String TO_PREFIX = "To_";
+ public static final String FROM_PREFIX = "From_";
+ public static final String END_TRANSACTION = "EndTransaction";
+ public static final String ROCKETMQ_SERVICE = "rocketmq";
+ public static final String ROCKETMQ_SUCCESS = "rocketmq.success";
+ public static final String ROCKETMQ_TAGS = "rocketmq.tags";
+ public static final String ROCKETMQ_KEYS = "rocketmq.keys";
+ public static final String ROCKETMQ_SOTRE_HOST = "rocketmq.store_host";
+ public static final String ROCKETMQ_BODY_LENGTH = "rocketmq.body_length";
+ public static final String ROCKETMQ_MSG_ID = "rocketmq.mgs_id";
+ public static final String ROCKETMQ_MSG_TYPE = "rocketmq.mgs_type";
+ public static final String ROCKETMQ_REGION_ID = "rocketmq.region_id";
+ public static final String ROCKETMQ_TRANSACTION_ID = "rocketmq.transaction_id";
+ public static final String ROCKETMQ_TRANSACTION_STATE = "rocketmq.transaction_state";
+ public static final String ROCKETMQ_IS_FROM_TRANSACTION_CHECK = "rocketmq.is_from_transaction_check";
+ public static final String ROCKETMQ_RETRY_TIMERS = "rocketmq.retry_times";
}
diff --git a/client/src/main/java/org/apache/rocketmq/client/trace/TraceDataEncoder.java b/client/src/main/java/org/apache/rocketmq/client/trace/TraceDataEncoder.java
index acf0dea8b8..2625d353f8 100644
--- a/client/src/main/java/org/apache/rocketmq/client/trace/TraceDataEncoder.java
+++ b/client/src/main/java/org/apache/rocketmq/client/trace/TraceDataEncoder.java
@@ -16,6 +16,7 @@
*/
package org.apache.rocketmq.client.trace;
+import org.apache.rocketmq.client.producer.LocalTransactionState;
import org.apache.rocketmq.common.message.MessageType;
import java.util.ArrayList;
@@ -109,6 +110,27 @@ public class TraceDataEncoder {
subAfterContext.setGroupName(line[8]);
}
resList.add(subAfterContext);
+ } else if (line[0].equals(TraceType.EndTransaction.name())) {
+ TraceContext endTransactionContext = new TraceContext();
+ endTransactionContext.setTraceType(TraceType.EndTransaction);
+ endTransactionContext.setTimeStamp(Long.parseLong(line[1]));
+ endTransactionContext.setRegionId(line[2]);
+ endTransactionContext.setGroupName(line[3]);
+ TraceBean bean = new TraceBean();
+ bean.setTopic(line[4]);
+ bean.setMsgId(line[5]);
+ bean.setTags(line[6]);
+ bean.setKeys(line[7]);
+ bean.setStoreHost(line[8]);
+ bean.setMsgType(MessageType.values()[Integer.parseInt(line[9])]);
+ bean.setClientHost(line[10]);
+ bean.setTransactionId(line[11]);
+ bean.setTransactionState(LocalTransactionState.valueOf(line[12]));
+ bean.setFromTransactionCheck(Boolean.parseBoolean(line[13]));
+
+ endTransactionContext.setTraceBeans(new ArrayList(1));
+ endTransactionContext.getTraceBeans().add(bean);
+ resList.add(endTransactionContext);
}
}
return resList;
@@ -173,10 +195,28 @@ public class TraceDataEncoder {
.append(ctx.getContextCode()).append(TraceConstants.CONTENT_SPLITOR)
.append(ctx.getTimeStamp()).append(TraceConstants.CONTENT_SPLITOR)
.append(ctx.getGroupName()).append(TraceConstants.FIELD_SPLITOR);
-
+
}
}
break;
+ case EndTransaction: {
+ TraceBean bean = ctx.getTraceBeans().get(0);
+ sb.append(ctx.getTraceType()).append(TraceConstants.CONTENT_SPLITOR)//
+ .append(ctx.getTimeStamp()).append(TraceConstants.CONTENT_SPLITOR)//
+ .append(ctx.getRegionId()).append(TraceConstants.CONTENT_SPLITOR)//
+ .append(ctx.getGroupName()).append(TraceConstants.CONTENT_SPLITOR)//
+ .append(bean.getTopic()).append(TraceConstants.CONTENT_SPLITOR)//
+ .append(bean.getMsgId()).append(TraceConstants.CONTENT_SPLITOR)//
+ .append(bean.getTags()).append(TraceConstants.CONTENT_SPLITOR)//
+ .append(bean.getKeys()).append(TraceConstants.CONTENT_SPLITOR)//
+ .append(bean.getStoreHost()).append(TraceConstants.CONTENT_SPLITOR)//
+ .append(bean.getMsgType().ordinal()).append(TraceConstants.CONTENT_SPLITOR)//
+ .append(bean.getClientHost()).append(TraceConstants.CONTENT_SPLITOR)//
+ .append(bean.getTransactionId()).append(TraceConstants.CONTENT_SPLITOR)//
+ .append(bean.getTransactionState().name()).append(TraceConstants.CONTENT_SPLITOR)//
+ .append(bean.isFromTransactionCheck()).append(TraceConstants.FIELD_SPLITOR);
+ }
+ break;
default:
}
transferBean.setTransData(sb.toString());
diff --git a/client/src/main/java/org/apache/rocketmq/client/trace/TraceType.java b/client/src/main/java/org/apache/rocketmq/client/trace/TraceType.java
index 79b19c17e4..8870ddcbdb 100644
--- a/client/src/main/java/org/apache/rocketmq/client/trace/TraceType.java
+++ b/client/src/main/java/org/apache/rocketmq/client/trace/TraceType.java
@@ -20,4 +20,5 @@ public enum TraceType {
Pub,
SubBefore,
SubAfter,
+ EndTransaction,
}
diff --git a/client/src/main/java/org/apache/rocketmq/client/trace/hook/ConsumeMessageOpenTracingHookImpl.java b/client/src/main/java/org/apache/rocketmq/client/trace/hook/ConsumeMessageOpenTracingHookImpl.java
new file mode 100644
index 0000000000..28fccae06f
--- /dev/null
+++ b/client/src/main/java/org/apache/rocketmq/client/trace/hook/ConsumeMessageOpenTracingHookImpl.java
@@ -0,0 +1,95 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.rocketmq.client.trace.hook;
+
+import io.opentracing.Span;
+import io.opentracing.SpanContext;
+import io.opentracing.Tracer;
+import io.opentracing.propagation.Format;
+import io.opentracing.propagation.TextMapAdapter;
+import io.opentracing.tag.Tags;
+import org.apache.rocketmq.client.hook.ConsumeMessageContext;
+import org.apache.rocketmq.client.hook.ConsumeMessageHook;
+import org.apache.rocketmq.client.trace.TraceConstants;
+import org.apache.rocketmq.common.message.MessageConst;
+import org.apache.rocketmq.common.message.MessageExt;
+import org.apache.rocketmq.common.protocol.NamespaceUtil;
+
+import java.util.ArrayList;
+import java.util.List;
+
+
+public class ConsumeMessageOpenTracingHookImpl implements ConsumeMessageHook {
+
+ private Tracer tracer;
+
+ public ConsumeMessageOpenTracingHookImpl(Tracer tracer) {
+ this.tracer = tracer;
+ }
+
+ @Override
+ public String hookName() {
+ return "ConsumeMessageOpenTracingHook";
+ }
+
+ @Override
+ public void consumeMessageBefore(ConsumeMessageContext context) {
+ if (context == null || context.getMsgList() == null || context.getMsgList().isEmpty()) {
+ return;
+ }
+ List spanList = new ArrayList<>();
+ for (MessageExt msg : context.getMsgList()) {
+ if (msg == null) {
+ continue;
+ }
+ Tracer.SpanBuilder spanBuilder = tracer
+ .buildSpan(TraceConstants.FROM_PREFIX + msg.getTopic())
+ .withTag(Tags.SPAN_KIND, Tags.SPAN_KIND_CONSUMER);
+ SpanContext spanContext = tracer.extract(Format.Builtin.TEXT_MAP, new TextMapAdapter(msg.getProperties()));
+ if (spanContext != null) {
+ spanBuilder.asChildOf(spanContext);
+ }
+ Span span = spanBuilder.start();
+
+ span.setTag(Tags.PEER_SERVICE, TraceConstants.ROCKETMQ_SERVICE);
+ span.setTag(Tags.MESSAGE_BUS_DESTINATION, NamespaceUtil.withoutNamespace(msg.getTopic()));
+ span.setTag(TraceConstants.ROCKETMQ_MSG_ID, msg.getMsgId());
+ span.setTag(TraceConstants.ROCKETMQ_TAGS, msg.getTags());
+ span.setTag(TraceConstants.ROCKETMQ_KEYS, msg.getKeys());
+ span.setTag(TraceConstants.ROCKETMQ_BODY_LENGTH, msg.getStoreSize());
+ span.setTag(TraceConstants.ROCKETMQ_RETRY_TIMERS, msg.getReconsumeTimes());
+ span.setTag(TraceConstants.ROCKETMQ_REGION_ID, msg.getProperty(MessageConst.PROPERTY_MSG_REGION));
+ spanList.add(span);
+ }
+ context.setMqTraceContext(spanList);
+ }
+
+ @Override
+ public void consumeMessageAfter(ConsumeMessageContext context) {
+ if (context == null || context.getMsgList() == null || context.getMsgList().isEmpty()) {
+ return;
+ }
+ List spanList = (List) context.getMqTraceContext();
+ if (spanList == null) {
+ return;
+ }
+ for (Span span : spanList) {
+ span.setTag(TraceConstants.ROCKETMQ_SUCCESS, context.isSuccess());
+ span.finish();
+ }
+ }
+}
diff --git a/client/src/main/java/org/apache/rocketmq/client/trace/hook/EndTransactionOpenTracingHookImpl.java b/client/src/main/java/org/apache/rocketmq/client/trace/hook/EndTransactionOpenTracingHookImpl.java
new file mode 100644
index 0000000000..62d310f196
--- /dev/null
+++ b/client/src/main/java/org/apache/rocketmq/client/trace/hook/EndTransactionOpenTracingHookImpl.java
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.rocketmq.client.trace.hook;
+
+import io.opentracing.Span;
+import io.opentracing.SpanContext;
+import io.opentracing.Tracer;
+import io.opentracing.propagation.Format;
+import io.opentracing.propagation.TextMapAdapter;
+import io.opentracing.tag.Tags;
+import org.apache.rocketmq.client.hook.EndTransactionContext;
+import org.apache.rocketmq.client.hook.EndTransactionHook;
+import org.apache.rocketmq.client.trace.TraceConstants;
+import org.apache.rocketmq.common.message.Message;
+import org.apache.rocketmq.common.message.MessageType;
+
+public class EndTransactionOpenTracingHookImpl implements EndTransactionHook {
+
+ private Tracer tracer;
+
+ public EndTransactionOpenTracingHookImpl(Tracer tracer) {
+ this.tracer = tracer;
+ }
+
+ @Override
+ public String hookName() {
+ return "EndTransactionOpenTracingHook";
+ }
+
+ @Override
+ public void endTransaction(EndTransactionContext context) {
+ if (context == null) {
+ return;
+ }
+ Message msg = context.getMessage();
+ Tracer.SpanBuilder spanBuilder = tracer
+ .buildSpan(TraceConstants.END_TRANSACTION)
+ .withTag(Tags.SPAN_KIND, Tags.SPAN_KIND_PRODUCER);
+ SpanContext spanContext = tracer.extract(Format.Builtin.TEXT_MAP, new TextMapAdapter(msg.getProperties()));
+ if (spanContext != null) {
+ spanBuilder.asChildOf(spanContext);
+ }
+
+ Span span = spanBuilder.start();
+ span.setTag(Tags.PEER_SERVICE, TraceConstants.ROCKETMQ_SERVICE);
+ span.setTag(Tags.MESSAGE_BUS_DESTINATION, msg.getTopic());
+ span.setTag(TraceConstants.ROCKETMQ_TAGS, msg.getTags());
+ span.setTag(TraceConstants.ROCKETMQ_KEYS, msg.getKeys());
+ span.setTag(TraceConstants.ROCKETMQ_SOTRE_HOST, context.getBrokerAddr());
+ span.setTag(TraceConstants.ROCKETMQ_MSG_ID, context.getMsgId());
+ span.setTag(TraceConstants.ROCKETMQ_MSG_TYPE, MessageType.Trans_msg_Commit.name());
+ span.setTag(TraceConstants.ROCKETMQ_TRANSACTION_ID, context.getTransactionId());
+ span.setTag(TraceConstants.ROCKETMQ_TRANSACTION_STATE, context.getTransactionState().name());
+ span.setTag(TraceConstants.ROCKETMQ_IS_FROM_TRANSACTION_CHECK, context.isFromTransactionCheck());
+ span.finish();
+ }
+
+}
diff --git a/client/src/main/java/org/apache/rocketmq/client/trace/hook/EndTransactionTraceHookImpl.java b/client/src/main/java/org/apache/rocketmq/client/trace/hook/EndTransactionTraceHookImpl.java
new file mode 100644
index 0000000000..cbd755ba39
--- /dev/null
+++ b/client/src/main/java/org/apache/rocketmq/client/trace/hook/EndTransactionTraceHookImpl.java
@@ -0,0 +1,81 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.rocketmq.client.trace.hook;
+
+import org.apache.rocketmq.client.hook.EndTransactionContext;
+import org.apache.rocketmq.client.hook.EndTransactionHook;
+import org.apache.rocketmq.client.trace.AsyncTraceDispatcher;
+import org.apache.rocketmq.client.trace.TraceBean;
+import org.apache.rocketmq.client.trace.TraceContext;
+import org.apache.rocketmq.client.trace.TraceDispatcher;
+import org.apache.rocketmq.client.trace.TraceType;
+import org.apache.rocketmq.common.MixAll;
+import org.apache.rocketmq.common.message.Message;
+import org.apache.rocketmq.common.message.MessageConst;
+import org.apache.rocketmq.common.message.MessageType;
+import org.apache.rocketmq.common.protocol.NamespaceUtil;
+
+import java.util.ArrayList;
+
+public class EndTransactionTraceHookImpl implements EndTransactionHook {
+
+ private TraceDispatcher localDispatcher;
+
+ public EndTransactionTraceHookImpl(TraceDispatcher localDispatcher) {
+ this.localDispatcher = localDispatcher;
+ }
+
+ @Override
+ public String hookName() {
+ return "EndTransactionTraceHook";
+ }
+
+ @Override
+ public void endTransaction(EndTransactionContext context) {
+ //if it is message trace data,then it doesn't recorded
+ if (context == null || context.getMessage().getTopic().startsWith(((AsyncTraceDispatcher) localDispatcher).getTraceTopicName())) {
+ return;
+ }
+ Message msg = context.getMessage();
+ //build the context content of TuxeTraceContext
+ TraceContext tuxeContext = new TraceContext();
+ tuxeContext.setTraceBeans(new ArrayList(1));
+ tuxeContext.setTraceType(TraceType.EndTransaction);
+ tuxeContext.setGroupName(NamespaceUtil.withoutNamespace(context.getProducerGroup()));
+ //build the data bean object of message trace
+ TraceBean traceBean = new TraceBean();
+ traceBean.setTopic(NamespaceUtil.withoutNamespace(context.getMessage().getTopic()));
+ traceBean.setTags(context.getMessage().getTags());
+ traceBean.setKeys(context.getMessage().getKeys());
+ traceBean.setStoreHost(context.getBrokerAddr());
+ traceBean.setMsgType(MessageType.Trans_msg_Commit);
+ traceBean.setClientHost(((AsyncTraceDispatcher)localDispatcher).getHostProducer().getmQClientFactory().getClientId());
+ traceBean.setMsgId(context.getMsgId());
+ traceBean.setTransactionState(context.getTransactionState());
+ traceBean.setTransactionId(context.getTransactionId());
+ traceBean.setFromTransactionCheck(context.isFromTransactionCheck());
+ String regionId = msg.getProperty(MessageConst.PROPERTY_MSG_REGION);
+ if (regionId == null || regionId.isEmpty()) {
+ regionId = MixAll.DEFAULT_TRACE_REGION_ID;
+ }
+ tuxeContext.setRegionId(regionId);
+ tuxeContext.getTraceBeans().add(traceBean);
+ tuxeContext.setTimeStamp(System.currentTimeMillis());
+ localDispatcher.append(tuxeContext);
+ }
+
+}
diff --git a/client/src/main/java/org/apache/rocketmq/client/trace/hook/SendMessageOpenTracingHookImpl.java b/client/src/main/java/org/apache/rocketmq/client/trace/hook/SendMessageOpenTracingHookImpl.java
new file mode 100644
index 0000000000..60c18a22a7
--- /dev/null
+++ b/client/src/main/java/org/apache/rocketmq/client/trace/hook/SendMessageOpenTracingHookImpl.java
@@ -0,0 +1,88 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.rocketmq.client.trace.hook;
+
+import io.opentracing.Span;
+import io.opentracing.SpanContext;
+import io.opentracing.Tracer;
+import io.opentracing.propagation.Format;
+import io.opentracing.propagation.TextMapAdapter;
+import io.opentracing.tag.Tags;
+import org.apache.rocketmq.client.hook.SendMessageContext;
+import org.apache.rocketmq.client.hook.SendMessageHook;
+import org.apache.rocketmq.client.producer.SendStatus;
+import org.apache.rocketmq.client.trace.TraceConstants;
+import org.apache.rocketmq.common.message.Message;
+
+public class SendMessageOpenTracingHookImpl implements SendMessageHook {
+
+ private Tracer tracer;
+
+ public SendMessageOpenTracingHookImpl(Tracer tracer) {
+ this.tracer = tracer;
+ }
+
+ @Override
+ public String hookName() {
+ return "SendMessageOpenTracingHook";
+ }
+
+ @Override
+ public void sendMessageBefore(SendMessageContext context) {
+ if (context == null) {
+ return;
+ }
+ Message msg = context.getMessage();
+ Tracer.SpanBuilder spanBuilder = tracer
+ .buildSpan(TraceConstants.TO_PREFIX + msg.getTopic())
+ .withTag(Tags.SPAN_KIND, Tags.SPAN_KIND_PRODUCER);
+ SpanContext spanContext = tracer.extract(Format.Builtin.TEXT_MAP, new TextMapAdapter(msg.getProperties()));
+ if (spanContext != null) {
+ spanBuilder.asChildOf(spanContext);
+ }
+ Span span = spanBuilder.start();
+ tracer.inject(span.context(), Format.Builtin.TEXT_MAP, new TextMapAdapter(msg.getProperties()));
+ span.setTag(Tags.PEER_SERVICE, TraceConstants.ROCKETMQ_SERVICE);
+ span.setTag(Tags.MESSAGE_BUS_DESTINATION, msg.getTopic());
+ span.setTag(TraceConstants.ROCKETMQ_TAGS, msg.getTags());
+ span.setTag(TraceConstants.ROCKETMQ_KEYS, msg.getKeys());
+ span.setTag(TraceConstants.ROCKETMQ_SOTRE_HOST, context.getBrokerAddr());
+ span.setTag(TraceConstants.ROCKETMQ_MSG_TYPE, context.getMsgType().name());
+ span.setTag(TraceConstants.ROCKETMQ_BODY_LENGTH, msg.getBody().length);
+ context.setMqTraceContext(span);
+ }
+
+ @Override
+ public void sendMessageAfter(SendMessageContext context) {
+ if (context == null || context.getMqTraceContext() == null) {
+ return;
+ }
+ if (context.getSendResult() == null) {
+ return;
+ }
+
+ if (context.getSendResult().getRegionId() == null) {
+ return;
+ }
+
+ Span span = (Span) context.getMqTraceContext();
+ span.setTag(TraceConstants.ROCKETMQ_SUCCESS, context.getSendResult().getSendStatus().equals(SendStatus.SEND_OK));
+ span.setTag(TraceConstants.ROCKETMQ_MSG_ID, context.getSendResult().getMsgId());
+ span.setTag(TraceConstants.ROCKETMQ_REGION_ID, context.getSendResult().getRegionId());
+ span.finish();
+ }
+}
diff --git a/client/src/test/java/org/apache/rocketmq/client/common/ThreadLocalIndexTest.java b/client/src/test/java/org/apache/rocketmq/client/common/ThreadLocalIndexTest.java
index 1be93ce0f3..de35b9181b 100644
--- a/client/src/test/java/org/apache/rocketmq/client/common/ThreadLocalIndexTest.java
+++ b/client/src/test/java/org/apache/rocketmq/client/common/ThreadLocalIndexTest.java
@@ -22,11 +22,18 @@ import static org.assertj.core.api.Assertions.assertThat;
public class ThreadLocalIndexTest {
@Test
- public void testGetAndIncrement() throws Exception {
+ public void testIncrementAndGet() throws Exception {
ThreadLocalIndex localIndex = new ThreadLocalIndex();
- int initialVal = localIndex.getAndIncrement();
+ int initialVal = localIndex.incrementAndGet();
- assertThat(localIndex.getAndIncrement()).isEqualTo(initialVal + 1);
+ assertThat(localIndex.incrementAndGet()).isEqualTo(initialVal + 1);
+ }
+
+ @Test
+ public void testIncrementAndGet2() throws Exception {
+ ThreadLocalIndex localIndex = new ThreadLocalIndex();
+ int initialVal = localIndex.incrementAndGet();
+ assertThat(initialVal >= 0);
}
}
\ No newline at end of file
diff --git a/client/src/test/java/org/apache/rocketmq/client/consumer/DefaultLitePullConsumerTest.java b/client/src/test/java/org/apache/rocketmq/client/consumer/DefaultLitePullConsumerTest.java
index 66832706eb..04b760eec2 100644
--- a/client/src/test/java/org/apache/rocketmq/client/consumer/DefaultLitePullConsumerTest.java
+++ b/client/src/test/java/org/apache/rocketmq/client/consumer/DefaultLitePullConsumerTest.java
@@ -20,8 +20,12 @@ package org.apache.rocketmq.client.consumer;
import java.io.ByteArrayOutputStream;
import java.lang.reflect.Field;
import java.net.InetSocketAddress;
-import java.util.*;
-
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.ConcurrentMap;
+import org.apache.commons.lang3.reflect.FieldUtils;
import org.apache.rocketmq.client.ClientConfig;
import org.apache.rocketmq.client.consumer.store.OffsetStore;
import org.apache.rocketmq.client.consumer.store.ReadOffsetType;
@@ -46,16 +50,15 @@ import org.apache.rocketmq.common.message.MessageExt;
import org.apache.rocketmq.common.message.MessageQueue;
import org.apache.rocketmq.common.protocol.header.PullMessageRequestHeader;
import org.apache.rocketmq.common.protocol.heartbeat.MessageModel;
+import org.apache.rocketmq.remoting.RPCHook;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.Spy;
import org.mockito.invocation.InvocationOnMock;
+import org.mockito.junit.MockitoJUnitRunner;
import org.mockito.stubbing.Answer;
-import org.powermock.api.mockito.PowerMockito;
-import org.powermock.core.classloader.annotations.PrepareForTest;
-import org.powermock.modules.junit4.PowerMockRunner;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Fail.failBecauseExceptionWasNotThrown;
@@ -69,8 +72,7 @@ import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
-@RunWith(PowerMockRunner.class)
-@PrepareForTest(DefaultLitePullConsumerImpl.class)
+@RunWith(MockitoJUnitRunner.class)
public class DefaultLitePullConsumerTest {
@Spy
private MQClientInstance mQClientFactory = MQClientManager.getInstance().getOrCreateMQClientInstance(new ClientConfig());
@@ -92,7 +94,10 @@ public class DefaultLitePullConsumerTest {
@Before
public void init() throws Exception {
- PowerMockito.suppress(PowerMockito.method(DefaultLitePullConsumerImpl.class, "updateTopicSubscribeInfoWhenSubscriptionChanged"));
+ ConcurrentMap factoryTable = (ConcurrentMap) FieldUtils.readDeclaredField(MQClientManager.getInstance(), "factoryTable", true);
+ factoryTable.forEach((s, instance) -> instance.shutdown());
+ factoryTable.clear();
+
Field field = MQClientInstance.class.getDeclaredField("rebalanceService");
field.setAccessible(true);
RebalanceService rebalanceService = (RebalanceService) field.get(mQClientFactory);
@@ -180,7 +185,9 @@ public class DefaultLitePullConsumerTest {
when(mQAdminImpl.minOffset(any(MessageQueue.class))).thenReturn(0L);
when(mQAdminImpl.maxOffset(any(MessageQueue.class))).thenReturn(500L);
MessageQueue messageQueue = createMessageQueue();
- litePullConsumer.assign(Collections.singletonList(messageQueue));
+ List messageQueues = Collections.singletonList(messageQueue);
+ litePullConsumer.assign(messageQueues);
+ litePullConsumer.pause(messageQueues);
long offset = litePullConsumer.committed(messageQueue);
litePullConsumer.seek(messageQueue, offset);
Field field = DefaultLitePullConsumerImpl.class.getDeclaredField("assignedMessageQueue");
@@ -196,7 +203,9 @@ public class DefaultLitePullConsumerTest {
when(mQAdminImpl.minOffset(any(MessageQueue.class))).thenReturn(0L);
when(mQAdminImpl.maxOffset(any(MessageQueue.class))).thenReturn(500L);
MessageQueue messageQueue = createMessageQueue();
- litePullConsumer.assign(Collections.singletonList(messageQueue));
+ List messageQueues = Collections.singletonList(messageQueue);
+ litePullConsumer.assign(messageQueues);
+ litePullConsumer.pause(messageQueues);
litePullConsumer.seekToBegin(messageQueue);
Field field = DefaultLitePullConsumerImpl.class.getDeclaredField("assignedMessageQueue");
field.setAccessible(true);
@@ -211,7 +220,9 @@ public class DefaultLitePullConsumerTest {
when(mQAdminImpl.minOffset(any(MessageQueue.class))).thenReturn(0L);
when(mQAdminImpl.maxOffset(any(MessageQueue.class))).thenReturn(500L);
MessageQueue messageQueue = createMessageQueue();
- litePullConsumer.assign(Collections.singletonList(messageQueue));
+ List messageQueues = Collections.singletonList(messageQueue);
+ litePullConsumer.assign(messageQueues);
+ litePullConsumer.pause(messageQueues);
litePullConsumer.seekToEnd(messageQueue);
Field field = DefaultLitePullConsumerImpl.class.getDeclaredField("assignedMessageQueue");
field.setAccessible(true);
@@ -226,7 +237,9 @@ public class DefaultLitePullConsumerTest {
when(mQAdminImpl.minOffset(any(MessageQueue.class))).thenReturn(0L);
when(mQAdminImpl.maxOffset(any(MessageQueue.class))).thenReturn(100L);
MessageQueue messageQueue = createMessageQueue();
- litePullConsumer.assign(Collections.singletonList(messageQueue));
+ List messageQueues = Collections.singletonList(messageQueue);
+ litePullConsumer.assign(messageQueues);
+ litePullConsumer.pause(messageQueues);
try {
litePullConsumer.seek(messageQueue, -1);
failBecauseExceptionWasNotThrown(MQClientException.class);
@@ -515,9 +528,6 @@ public class DefaultLitePullConsumerTest {
public void testConsumerAfterShutdown() throws Exception {
DefaultLitePullConsumer defaultLitePullConsumer = createSubscribeLitePullConsumer();
- DefaultLitePullConsumer mockConsumer = spy(defaultLitePullConsumer);
- when(mockConsumer.poll(anyLong())).thenReturn(new ArrayList<>());
-
new AsyncConsumer().executeAsync(defaultLitePullConsumer);
Thread.sleep(100);
@@ -574,9 +584,9 @@ public class DefaultLitePullConsumerTest {
when(mQClientFactory.getMQClientAPIImpl().pullMessage(anyString(), any(PullMessageRequestHeader.class),
anyLong(), any(CommunicationMode.class), nullable(PullCallback.class)))
- .thenAnswer(new Answer
+
+ io.jaegertracing
+ jaeger-core
+ 1.6.0
+
+
+ io.jaegertracing
+ jaeger-client
+ 1.6.0
+
diff --git a/example/src/main/java/org/apache/rocketmq/example/benchmark/Consumer.java b/example/src/main/java/org/apache/rocketmq/example/benchmark/Consumer.java
index c0a2a8b53a..8a6429b2aa 100644
--- a/example/src/main/java/org/apache/rocketmq/example/benchmark/Consumer.java
+++ b/example/src/main/java/org/apache/rocketmq/example/benchmark/Consumer.java
@@ -52,8 +52,9 @@ public class Consumer {
}
final String topic = commandLine.hasOption('t') ? commandLine.getOptionValue('t').trim() : "BenchmarkTest";
+ final int threadCount = commandLine.hasOption('w') ? Integer.parseInt(commandLine.getOptionValue('w')) : 20;
final String groupPrefix = commandLine.hasOption('g') ? commandLine.getOptionValue('g').trim() : "benchmark_consumer";
- final String isSuffixEnable = commandLine.hasOption('p') ? commandLine.getOptionValue('p').trim() : "true";
+ final String isSuffixEnable = commandLine.hasOption('p') ? commandLine.getOptionValue('p').trim() : "false";
final String filterType = commandLine.hasOption('f') ? commandLine.getOptionValue('f').trim() : null;
final String expression = commandLine.hasOption('e') ? commandLine.getOptionValue('e').trim() : null;
final double failRate = commandLine.hasOption('r') ? Double.parseDouble(commandLine.getOptionValue('r').trim()) : 0.0;
@@ -65,8 +66,8 @@ public class Consumer {
group = groupPrefix + "_" + (System.currentTimeMillis() % 100);
}
- System.out.printf("topic: %s, group: %s, suffix: %s, filterType: %s, expression: %s, msgTraceEnable: %s, aclEnable: %s%n",
- topic, group, isSuffixEnable, filterType, expression, msgTraceEnable, aclEnable);
+ System.out.printf("topic: %s, threadCount %d, group: %s, suffix: %s, filterType: %s, expression: %s, msgTraceEnable: %s, aclEnable: %s%n",
+ topic, threadCount, group, isSuffixEnable, filterType, expression, msgTraceEnable, aclEnable);
final StatsBenchmarkConsumer statsBenchmarkConsumer = new StatsBenchmarkConsumer();
@@ -101,8 +102,8 @@ public class Consumer {
statsBenchmarkConsumer.getBorn2ConsumerMaxRT().set(0);
statsBenchmarkConsumer.getStore2ConsumerMaxRT().set(0);
- System.out.printf("TPS: %d FAIL: %d AVG(B2C) RT: %7.3f AVG(S2C) RT: %7.3f MAX(B2C) RT: %d MAX(S2C) RT: %d%n",
- consumeTps, failCount, averageB2CRT, averageS2CRT, b2cMax, s2cMax
+ System.out.printf("Current Time: %s TPS: %d FAIL: %d AVG(B2C) RT(ms): %7.3f AVG(S2C) RT(ms): %7.3f MAX(B2C) RT(ms): %d MAX(S2C) RT(ms): %d%n",
+ System.currentTimeMillis(), consumeTps, failCount, averageB2CRT, averageS2CRT, b2cMax, s2cMax
);
}
}
@@ -123,6 +124,8 @@ public class Consumer {
String ns = commandLine.getOptionValue('n');
consumer.setNamesrvAddr(ns);
}
+ consumer.setConsumeThreadMin(threadCount);
+ consumer.setConsumeThreadMax(threadCount);
consumer.setInstanceName(Long.toString(System.currentTimeMillis()));
if (filterType == null || expression == null) {
@@ -179,11 +182,15 @@ public class Consumer {
opt.setRequired(false);
options.addOption(opt);
+ opt = new Option("w", "threadCount", true, "Thread count, Default: 20");
+ opt.setRequired(false);
+ options.addOption(opt);
+
opt = new Option("g", "group", true, "Consumer group name, Default: benchmark_consumer");
opt.setRequired(false);
options.addOption(opt);
- opt = new Option("p", "group prefix enable", true, "Consumer group name, Default: false");
+ opt = new Option("p", "group suffix enable", true, "Consumer group suffix enable, Default: false");
opt.setRequired(false);
options.addOption(opt);
diff --git a/example/src/main/java/org/apache/rocketmq/example/benchmark/Producer.java b/example/src/main/java/org/apache/rocketmq/example/benchmark/Producer.java
index dbad169221..6975ab58b0 100644
--- a/example/src/main/java/org/apache/rocketmq/example/benchmark/Producer.java
+++ b/example/src/main/java/org/apache/rocketmq/example/benchmark/Producer.java
@@ -17,12 +17,14 @@
package org.apache.rocketmq.example.benchmark;
import java.io.UnsupportedEncodingException;
+import java.util.Arrays;
import java.util.LinkedList;
import java.util.Random;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;
import org.apache.commons.cli.CommandLine;
@@ -41,6 +43,7 @@ import org.apache.rocketmq.remoting.exception.RemotingException;
import org.apache.rocketmq.srvutil.ServerUtil;
public class Producer {
+
public static void main(String[] args) throws MQClientException, UnsupportedEncodingException {
Options options = ServerUtil.buildCommandlineOptions(new Options());
@@ -54,11 +57,13 @@ public class Producer {
final int messageSize = commandLine.hasOption('s') ? Integer.parseInt(commandLine.getOptionValue('s')) : 128;
final boolean keyEnable = commandLine.hasOption('k') && Boolean.parseBoolean(commandLine.getOptionValue('k'));
final int propertySize = commandLine.hasOption('p') ? Integer.parseInt(commandLine.getOptionValue('p')) : 0;
+ final int tagCount = commandLine.hasOption('l') ? Integer.parseInt(commandLine.getOptionValue('l')) : 0;
final boolean msgTraceEnable = commandLine.hasOption('m') && Boolean.parseBoolean(commandLine.getOptionValue('m'));
final boolean aclEnable = commandLine.hasOption('a') && Boolean.parseBoolean(commandLine.getOptionValue('a'));
+ final long messageNum = commandLine.hasOption('q') ? Long.parseLong(commandLine.getOptionValue('q')) : 0;
- System.out.printf("topic %s threadCount %d messageSize %d keyEnable %s traceEnable %s aclEnable %s%n",
- topic, threadCount, messageSize, keyEnable, msgTraceEnable, aclEnable);
+ System.out.printf("topic: %s threadCount: %d messageSize: %d keyEnable: %s propertySize: %d tagCount: %d traceEnable: %s aclEnable: %s messageQuantity: %d%n",
+ topic, threadCount, messageSize, keyEnable, propertySize, tagCount, msgTraceEnable, aclEnable, messageNum);
final InternalLogger log = ClientLogger.getLog();
@@ -70,6 +75,16 @@ public class Producer {
final LinkedList snapshotList = new LinkedList();
+ final long[] msgNums = new long[threadCount];
+
+ if (messageNum > 0) {
+ Arrays.fill(msgNums, messageNum / threadCount);
+ long mod = messageNum % threadCount;
+ if (mod > 0) {
+ msgNums[0] += mod;
+ }
+ }
+
timer.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
@@ -83,14 +98,7 @@ public class Producer {
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]);
+ doPrintStats(snapshotList, statsBenchmark, false);
}
}
@@ -118,9 +126,14 @@ public class Producer {
producer.start();
for (int i = 0; i < threadCount; i++) {
+ final long msgNumLimit = msgNums[i];
+ if (messageNum > 0 && msgNumLimit == 0) {
+ break;
+ }
sendThreadPool.execute(new Runnable() {
@Override
public void run() {
+ int num = 0;
while (true) {
try {
final Message msg;
@@ -134,6 +147,10 @@ public class Producer {
if (keyEnable) {
msg.setKeys(String.valueOf(beginTimestamp / 1000));
}
+ if (tagCount > 0) {
+ long sendSucCount = statsBenchmark.getReceiveResponseSuccessCount().get();
+ msg.setTags(String.format("tag%d", sendSucCount % tagCount));
+ }
if (propertySize > 0) {
if (msg.getProperties() != null) {
msg.getProperties().clear();
@@ -192,10 +209,28 @@ public class Producer {
} catch (InterruptedException ignored) {
}
}
+ if (messageNum > 0 && ++num >= msgNumLimit) {
+ break;
+ }
}
}
});
}
+ try {
+ sendThreadPool.shutdown();
+ sendThreadPool.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS);
+ timer.cancel();
+ if (snapshotList.size() > 1) {
+ doPrintStats(snapshotList, statsBenchmark, true);
+ } else {
+ System.out.printf("[Complete] Send Total: %d Send Failed: %d Response Failed: %d%n",
+ statsBenchmark.getSendRequestSuccessCount().get() + statsBenchmark.getSendRequestFailedCount().get(),
+ statsBenchmark.getSendRequestFailedCount().get(), statsBenchmark.getReceiveResponseFailedCount().get());
+ }
+ producer.shutdown();
+ } catch (InterruptedException e) {
+ log.error("[Exit] Thread Interrupted Exception", e);
+ }
}
public static Options buildCommandlineOptions(final Options options) {
@@ -215,6 +250,10 @@ public class Producer {
opt.setRequired(false);
options.addOption(opt);
+ opt = new Option("l", "tagCount", true, "Tag count, Default: 0");
+ opt.setRequired(false);
+ options.addOption(opt);
+
opt = new Option("m", "msgTraceEnable", true, "Message Trace Enable, Default: false");
opt.setRequired(false);
options.addOption(opt);
@@ -223,6 +262,10 @@ public class Producer {
opt.setRequired(false);
options.addOption(opt);
+ opt = new Option("q", "messageQuantity", true, "Send message quantity, Default: 0, running forever");
+ opt.setRequired(false);
+ options.addOption(opt);
+
return options;
}
@@ -239,6 +282,23 @@ public class Producer {
return msg;
}
+
+ private static void doPrintStats(final LinkedList snapshotList, final StatsBenchmarkProducer statsBenchmark, boolean done) {
+ 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]);
+
+ if (done) {
+ System.out.printf("[Complete] Send Total: %d Send TPS: %d Max RT(ms): %d Average RT(ms): %7.3f Send Failed: %d Response Failed: %d%n",
+ statsBenchmark.getSendRequestSuccessCount().get() + statsBenchmark.getSendRequestFailedCount().get(),
+ sendTps, statsBenchmark.getSendMessageMaxRT().get(), averageRT, end[2], end[4]);
+ } else {
+ System.out.printf("Current Time: %s Send TPS: %d Max RT(ms): %d Average RT(ms): %7.3f Send Failed: %d Response Failed: %d%n",
+ System.currentTimeMillis(), sendTps, statsBenchmark.getSendMessageMaxRT().get(), averageRT, end[2], end[4]);
+ }
+ }
}
class StatsBenchmarkProducer {
diff --git a/example/src/main/java/org/apache/rocketmq/example/benchmark/TransactionProducer.java b/example/src/main/java/org/apache/rocketmq/example/benchmark/TransactionProducer.java
index 951b718d1e..85af04eabb 100644
--- a/example/src/main/java/org/apache/rocketmq/example/benchmark/TransactionProducer.java
+++ b/example/src/main/java/org/apache/rocketmq/example/benchmark/TransactionProducer.java
@@ -105,8 +105,8 @@ public class TransactionProducer {
final long dupCheck = end.duplicatedCheck - begin.duplicatedCheck;
System.out.printf(
- "Send TPS:%5d Max RT:%5d AVG RT:%3.1f Send Failed: %d check: %d unexpectedCheck: %d duplicatedCheck: %d %n",
- sendTps, statsBenchmark.getSendMessageMaxRT().get(), averageRT, failCount, checkCount,
+ "Current Time: %s Send TPS:%5d Max RT(ms):%5d AVG RT(ms):%3.1f Send Failed: %d check: %d unexpectedCheck: %d duplicatedCheck: %d %n",
+ System.currentTimeMillis(), sendTps, statsBenchmark.getSendMessageMaxRT().get(), averageRT, failCount, checkCount,
unexpectedCheck, dupCheck);
statsBenchmark.getSendMessageMaxRT().set(0);
}
diff --git a/example/src/main/java/org/apache/rocketmq/example/ordermessage/Producer.java b/example/src/main/java/org/apache/rocketmq/example/ordermessage/Producer.java
index 6a6bdc7d71..c5d864fa3f 100644
--- a/example/src/main/java/org/apache/rocketmq/example/ordermessage/Producer.java
+++ b/example/src/main/java/org/apache/rocketmq/example/ordermessage/Producer.java
@@ -16,12 +16,9 @@
*/
package org.apache.rocketmq.example.ordermessage;
-import java.io.UnsupportedEncodingException;
-import java.util.List;
import org.apache.rocketmq.client.exception.MQBrokerException;
import org.apache.rocketmq.client.exception.MQClientException;
import org.apache.rocketmq.client.producer.DefaultMQProducer;
-import org.apache.rocketmq.client.producer.MQProducer;
import org.apache.rocketmq.client.producer.MessageQueueSelector;
import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.common.message.Message;
@@ -29,10 +26,13 @@ import org.apache.rocketmq.common.message.MessageQueue;
import org.apache.rocketmq.remoting.common.RemotingHelper;
import org.apache.rocketmq.remoting.exception.RemotingException;
+import java.io.UnsupportedEncodingException;
+import java.util.List;
+
public class Producer {
public static void main(String[] args) throws UnsupportedEncodingException {
try {
- MQProducer producer = new DefaultMQProducer("please_rename_unique_group_name");
+ DefaultMQProducer producer = new DefaultMQProducer("please_rename_unique_group_name");
producer.start();
String[] tags = new String[] {"TagA", "TagB", "TagC", "TagD", "TagE"};
diff --git a/example/src/main/java/org/apache/rocketmq/example/tracemessage/OpenTracingProducer.java b/example/src/main/java/org/apache/rocketmq/example/tracemessage/OpenTracingProducer.java
new file mode 100644
index 0000000000..cd9ae2792b
--- /dev/null
+++ b/example/src/main/java/org/apache/rocketmq/example/tracemessage/OpenTracingProducer.java
@@ -0,0 +1,68 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.rocketmq.example.tracemessage;
+
+import io.jaegertracing.Configuration;
+import io.jaegertracing.internal.samplers.ConstSampler;
+import io.opentracing.Tracer;
+import io.opentracing.util.GlobalTracer;
+import org.apache.rocketmq.client.exception.MQClientException;
+import org.apache.rocketmq.client.producer.DefaultMQProducer;
+import org.apache.rocketmq.client.producer.SendResult;
+import org.apache.rocketmq.client.trace.hook.SendMessageOpenTracingHookImpl;
+import org.apache.rocketmq.common.message.Message;
+import org.apache.rocketmq.remoting.common.RemotingHelper;
+
+public class OpenTracingProducer {
+ public static void main(String[] args) throws MQClientException {
+
+ Tracer tracer = initTracer();
+
+ DefaultMQProducer producer = new DefaultMQProducer("ProducerGroupName");
+ producer.getDefaultMQProducerImpl().registerSendMessageHook(new SendMessageOpenTracingHookImpl(tracer));
+ producer.start();
+
+ try {
+ Message msg = new Message("TopicTest",
+ "TagA",
+ "OrderID188",
+ "Hello world".getBytes(RemotingHelper.DEFAULT_CHARSET));
+ SendResult sendResult = producer.send(msg);
+ System.out.printf("%s%n", sendResult);
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ producer.shutdown();
+ }
+
+ private static Tracer initTracer() {
+ Configuration.SamplerConfiguration samplerConfig = Configuration.SamplerConfiguration.fromEnv()
+ .withType(ConstSampler.TYPE)
+ .withParam(1);
+ Configuration.ReporterConfiguration reporterConfig = Configuration.ReporterConfiguration.fromEnv()
+ .withLogSpans(true);
+
+ Configuration config = new Configuration("rocketmq")
+ .withSampler(samplerConfig)
+ .withReporter(reporterConfig);
+ GlobalTracer.registerIfAbsent(config.getTracer());
+ return config.getTracer();
+ }
+}
diff --git a/example/src/main/java/org/apache/rocketmq/example/tracemessage/OpenTracingPushConsumer.java b/example/src/main/java/org/apache/rocketmq/example/tracemessage/OpenTracingPushConsumer.java
new file mode 100644
index 0000000000..1d5d8a273b
--- /dev/null
+++ b/example/src/main/java/org/apache/rocketmq/example/tracemessage/OpenTracingPushConsumer.java
@@ -0,0 +1,71 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.rocketmq.example.tracemessage;
+
+import io.jaegertracing.Configuration;
+import io.jaegertracing.internal.samplers.ConstSampler;
+import io.opentracing.Tracer;
+import io.opentracing.util.GlobalTracer;
+import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer;
+import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyContext;
+import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus;
+import org.apache.rocketmq.client.consumer.listener.MessageListenerConcurrently;
+import org.apache.rocketmq.client.exception.MQClientException;
+import org.apache.rocketmq.client.trace.hook.ConsumeMessageOpenTracingHookImpl;
+import org.apache.rocketmq.common.consumer.ConsumeFromWhere;
+import org.apache.rocketmq.common.message.MessageExt;
+
+import java.util.List;
+
+public class OpenTracingPushConsumer {
+ public static void main(String[] args) throws InterruptedException, MQClientException {
+ Tracer tracer = initTracer();
+
+ DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("CID_JODIE_1");
+ consumer.getDefaultMQPushConsumerImpl().registerConsumeMessageHook(new ConsumeMessageOpenTracingHookImpl(tracer));
+
+ consumer.subscribe("TopicTest", "*");
+ consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_FIRST_OFFSET);
+
+ consumer.setConsumeTimestamp("20181109221800");
+ consumer.registerMessageListener(new MessageListenerConcurrently() {
+
+ @Override
+ public ConsumeConcurrentlyStatus consumeMessage(List msgs, ConsumeConcurrentlyContext context) {
+ System.out.printf("%s Receive New Messages: %s %n", Thread.currentThread().getName(), msgs);
+ return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
+ }
+ });
+ consumer.start();
+ System.out.printf("Consumer Started.%n");
+ }
+
+ private static Tracer initTracer() {
+ Configuration.SamplerConfiguration samplerConfig = Configuration.SamplerConfiguration.fromEnv()
+ .withType(ConstSampler.TYPE)
+ .withParam(1);
+ Configuration.ReporterConfiguration reporterConfig = Configuration.ReporterConfiguration.fromEnv()
+ .withLogSpans(true);
+
+ Configuration config = new Configuration("rocketmq")
+ .withSampler(samplerConfig)
+ .withReporter(reporterConfig);
+ GlobalTracer.registerIfAbsent(config.getTracer());
+ return config.getTracer();
+ }
+}
diff --git a/example/src/main/java/org/apache/rocketmq/example/tracemessage/OpenTracingTransactionProducer.java b/example/src/main/java/org/apache/rocketmq/example/tracemessage/OpenTracingTransactionProducer.java
new file mode 100644
index 0000000000..514f3ceb7f
--- /dev/null
+++ b/example/src/main/java/org/apache/rocketmq/example/tracemessage/OpenTracingTransactionProducer.java
@@ -0,0 +1,86 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.rocketmq.example.tracemessage;
+
+import io.jaegertracing.Configuration;
+import io.jaegertracing.internal.samplers.ConstSampler;
+import io.opentracing.Tracer;
+import io.opentracing.util.GlobalTracer;
+import org.apache.rocketmq.client.exception.MQClientException;
+import org.apache.rocketmq.client.producer.LocalTransactionState;
+import org.apache.rocketmq.client.producer.SendResult;
+import org.apache.rocketmq.client.producer.TransactionListener;
+import org.apache.rocketmq.client.producer.TransactionMQProducer;
+import org.apache.rocketmq.client.trace.hook.EndTransactionOpenTracingHookImpl;
+import org.apache.rocketmq.client.trace.hook.SendMessageOpenTracingHookImpl;
+import org.apache.rocketmq.common.message.Message;
+import org.apache.rocketmq.common.message.MessageExt;
+import org.apache.rocketmq.remoting.common.RemotingHelper;
+
+import java.io.UnsupportedEncodingException;
+
+public class OpenTracingTransactionProducer {
+ public static void main(String[] args) throws MQClientException, InterruptedException {
+ Tracer tracer = initTracer();
+
+ TransactionMQProducer producer = new TransactionMQProducer("please_rename_unique_group_name");
+ producer.getDefaultMQProducerImpl().registerSendMessageHook(new SendMessageOpenTracingHookImpl(tracer));
+ producer.getDefaultMQProducerImpl().registerEndTransactionHook(new EndTransactionOpenTracingHookImpl(tracer));
+
+ producer.setTransactionListener(new TransactionListener() {
+ @Override
+ public LocalTransactionState executeLocalTransaction(Message msg, Object arg) {
+ return LocalTransactionState.COMMIT_MESSAGE;
+ }
+
+ @Override
+ public LocalTransactionState checkLocalTransaction(MessageExt msg) {
+ return LocalTransactionState.COMMIT_MESSAGE;
+ }
+ });
+ producer.start();
+
+ try {
+ Message msg = new Message("TopicTest", "Tag", "KEY",
+ "Hello RocketMQ".getBytes(RemotingHelper.DEFAULT_CHARSET));
+ SendResult sendResult = producer.sendMessageInTransaction(msg, null);
+ System.out.printf("%s%n", sendResult);
+ } catch (MQClientException | UnsupportedEncodingException e) {
+ e.printStackTrace();
+ }
+
+ for (int i = 0; i < 100000; i++) {
+ Thread.sleep(1000);
+ }
+ producer.shutdown();
+ }
+
+ private static Tracer initTracer() {
+ Configuration.SamplerConfiguration samplerConfig = Configuration.SamplerConfiguration.fromEnv()
+ .withType(ConstSampler.TYPE)
+ .withParam(1);
+ Configuration.ReporterConfiguration reporterConfig = Configuration.ReporterConfiguration.fromEnv()
+ .withLogSpans(true);
+
+ Configuration config = new Configuration("rocketmq")
+ .withSampler(samplerConfig)
+ .withReporter(reporterConfig);
+ GlobalTracer.registerIfAbsent(config.getTracer());
+ return config.getTracer();
+ }
+}
diff --git a/filter/pom.xml b/filter/pom.xml
index 94bfd16b8c..c12dd1fb28 100644
--- a/filter/pom.xml
+++ b/filter/pom.xml
@@ -20,7 +20,7 @@
rocketmq-all
org.apache.rocketmq
- 4.8.0-SNAPSHOT
+ 4.8.1-SNAPSHOT
4.0.0
diff --git a/filter/src/main/java/org/apache/rocketmq/filter/parser/SimpleCharStream.java b/filter/src/main/java/org/apache/rocketmq/filter/parser/SimpleCharStream.java
index 53f7e1c297..c10250e3bb 100644
--- a/filter/src/main/java/org/apache/rocketmq/filter/parser/SimpleCharStream.java
+++ b/filter/src/main/java/org/apache/rocketmq/filter/parser/SimpleCharStream.java
@@ -36,8 +36,8 @@ public class SimpleCharStream {
* Position in buffer.
*/
public int bufpos = -1;
- protected int bufline[];
- protected int bufcolumn[];
+ protected int[] bufline;
+ protected int[] bufcolumn;
protected int column = 0;
protected int line = 1;
@@ -62,8 +62,8 @@ public class SimpleCharStream {
protected void ExpandBuff(boolean wrapAround) {
char[] newbuffer = new char[bufsize + 2048];
- int newbufline[] = new int[bufsize + 2048];
- int newbufcolumn[] = new int[bufsize + 2048];
+ int[] newbufline = new int[bufsize + 2048];
+ int[] newbufcolumn = new int[bufsize + 2048];
try {
if (wrapAround) {
diff --git a/logappender/pom.xml b/logappender/pom.xml
index b67d6f705f..a6e979a83e 100644
--- a/logappender/pom.xml
+++ b/logappender/pom.xml
@@ -19,7 +19,7 @@
org.apache.rocketmq
rocketmq-all
- 4.8.0-SNAPSHOT
+ 4.8.1-SNAPSHOT
4.0.0
rocketmq-logappender
diff --git a/logging/pom.xml b/logging/pom.xml
index 917e37a9e6..77d0f29a97 100644
--- a/logging/pom.xml
+++ b/logging/pom.xml
@@ -19,7 +19,7 @@
org.apache.rocketmq
rocketmq-all
- 4.8.0-SNAPSHOT
+ 4.8.1-SNAPSHOT
4.0.0
diff --git a/logging/src/main/java/org/apache/rocketmq/logging/inner/Level.java b/logging/src/main/java/org/apache/rocketmq/logging/inner/Level.java
index 487682cd44..0dc81d74e6 100755
--- a/logging/src/main/java/org/apache/rocketmq/logging/inner/Level.java
+++ b/logging/src/main/java/org/apache/rocketmq/logging/inner/Level.java
@@ -116,7 +116,6 @@ public class Level implements Serializable {
if (s.equals(OFF_NAME)) {
return Level.OFF;
}
-
if (s.equals(INFO_NAME)) {
return Level.INFO;
}
diff --git a/logging/src/main/java/org/apache/rocketmq/logging/inner/LoggingBuilder.java b/logging/src/main/java/org/apache/rocketmq/logging/inner/LoggingBuilder.java
index f457a69567..3ec440bc88 100644
--- a/logging/src/main/java/org/apache/rocketmq/logging/inner/LoggingBuilder.java
+++ b/logging/src/main/java/org/apache/rocketmq/logging/inner/LoggingBuilder.java
@@ -1201,7 +1201,7 @@ public class LoggingBuilder {
public String format(LoggingEvent event) {
StringBuilder sb = new StringBuilder();
- SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss,sss");
+ SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss,SSS");
String format = simpleDateFormat.format(new Date(event.timeStamp));
sb.append(format);
sb.append(" ");
diff --git a/logging/src/main/java/org/apache/rocketmq/logging/inner/SysLogger.java b/logging/src/main/java/org/apache/rocketmq/logging/inner/SysLogger.java
index b6d1049778..aaba4d6e89 100755
--- a/logging/src/main/java/org/apache/rocketmq/logging/inner/SysLogger.java
+++ b/logging/src/main/java/org/apache/rocketmq/logging/inner/SysLogger.java
@@ -33,13 +33,13 @@ public class SysLogger {
public static void debug(String msg) {
if (debugEnabled && !quietMode) {
- System.out.printf("%s", PREFIX + msg);
+ System.err.println(PREFIX + msg);
}
}
public static void debug(String msg, Throwable t) {
if (debugEnabled && !quietMode) {
- System.out.printf("%s", PREFIX + msg);
+ System.err.println(PREFIX + msg);
if (t != null) {
t.printStackTrace(System.out);
}
diff --git a/namesrv/pom.xml b/namesrv/pom.xml
index 9a7eb35047..c5d6d05bc2 100644
--- a/namesrv/pom.xml
+++ b/namesrv/pom.xml
@@ -19,7 +19,7 @@
org.apache.rocketmq
rocketmq-all
- 4.8.0-SNAPSHOT
+ 4.8.1-SNAPSHOT
4.0.0
diff --git a/namesrv/src/main/java/org/apache/rocketmq/namesrv/routeinfo/RouteInfoManager.java b/namesrv/src/main/java/org/apache/rocketmq/namesrv/routeinfo/RouteInfoManager.java
index ecd057a29a..edef87ce2d 100644
--- a/namesrv/src/main/java/org/apache/rocketmq/namesrv/routeinfo/RouteInfoManager.java
+++ b/namesrv/src/main/java/org/apache/rocketmq/namesrv/routeinfo/RouteInfoManager.java
@@ -220,7 +220,7 @@ public class RouteInfoManager {
queueData.setWriteQueueNums(topicConfig.getWriteQueueNums());
queueData.setReadQueueNums(topicConfig.getReadQueueNums());
queueData.setPerm(topicConfig.getPerm());
- queueData.setTopicSynFlag(topicConfig.getTopicSysFlag());
+ queueData.setTopicSysFlag(topicConfig.getTopicSysFlag());
List queueDataList = this.topicQueueTable.get(topicConfig.getTopicName());
if (null == queueDataList) {
@@ -684,7 +684,7 @@ public class RouteInfoManager {
String topic = topicEntry.getKey();
List queueDatas = topicEntry.getValue();
if (queueDatas != null && queueDatas.size() > 0
- && TopicSysFlag.hasUnitFlag(queueDatas.get(0).getTopicSynFlag())) {
+ && TopicSysFlag.hasUnitFlag(queueDatas.get(0).getTopicSysFlag())) {
topicList.getTopicList().add(topic);
}
}
@@ -710,7 +710,7 @@ public class RouteInfoManager {
String topic = topicEntry.getKey();
List queueDatas = topicEntry.getValue();
if (queueDatas != null && queueDatas.size() > 0
- && TopicSysFlag.hasUnitSubFlag(queueDatas.get(0).getTopicSynFlag())) {
+ && TopicSysFlag.hasUnitSubFlag(queueDatas.get(0).getTopicSysFlag())) {
topicList.getTopicList().add(topic);
}
}
@@ -736,8 +736,8 @@ public class RouteInfoManager {
String topic = topicEntry.getKey();
List queueDatas = topicEntry.getValue();
if (queueDatas != null && queueDatas.size() > 0
- && !TopicSysFlag.hasUnitFlag(queueDatas.get(0).getTopicSynFlag())
- && TopicSysFlag.hasUnitSubFlag(queueDatas.get(0).getTopicSynFlag())) {
+ && !TopicSysFlag.hasUnitFlag(queueDatas.get(0).getTopicSysFlag())
+ && TopicSysFlag.hasUnitSubFlag(queueDatas.get(0).getTopicSysFlag())) {
topicList.getTopicList().add(topic);
}
}
diff --git a/openmessaging/pom.xml b/openmessaging/pom.xml
index 8a0db607d9..7f0e937996 100644
--- a/openmessaging/pom.xml
+++ b/openmessaging/pom.xml
@@ -20,7 +20,7 @@
rocketmq-all
org.apache.rocketmq
- 4.8.0-SNAPSHOT
+ 4.8.1-SNAPSHOT
4.0.0
diff --git a/pom.xml b/pom.xml
index 9370ecfe57..39f368538e 100644
--- a/pom.xml
+++ b/pom.xml
@@ -29,7 +29,7 @@
2012
org.apache.rocketmq
rocketmq-all
- 4.8.0-SNAPSHOT
+ 4.8.1-SNAPSHOT
pom
Apache RocketMQ ${project.version}
http://rocketmq.apache.org/
@@ -102,7 +102,6 @@
${project.basedir}/../test/target/jacoco-it.exec
file:**/generated-sources/**,**/test/**
- 2.0.2
@@ -425,7 +424,7 @@
junit
junit
- 4.11
+ 4.13.2
test
@@ -437,19 +436,13 @@
org.mockito
mockito-core
- 2.23.0
+ 3.10.0
test
- org.powermock
- powermock-module-junit4
- ${powermock.version}
- test
-
-
- org.powermock
- powermock-api-mockito2
- ${powermock.version}
+ org.awaitility
+ awaitility
+ 4.1.0
test
@@ -549,7 +542,7 @@
com.alibaba
fastjson
- 1.2.70
+ 1.2.76
org.javassist
@@ -604,7 +597,7 @@
commons-validator
commons-validator
- 1.6
+ 1.7
diff --git a/remoting/pom.xml b/remoting/pom.xml
index 27f44eab31..d9dab9efa6 100644
--- a/remoting/pom.xml
+++ b/remoting/pom.xml
@@ -19,7 +19,7 @@
org.apache.rocketmq
rocketmq-all
- 4.8.0-SNAPSHOT
+ 4.8.1-SNAPSHOT
4.0.0
@@ -40,10 +40,5 @@
${project.groupId}
rocketmq-logging
-
- io.netty
- netty-tcnative-boringssl-static
- 1.1.33.Fork26
-
diff --git a/remoting/src/main/java/org/apache/rocketmq/remoting/common/RemotingUtil.java b/remoting/src/main/java/org/apache/rocketmq/remoting/common/RemotingUtil.java
index a16940e561..d936c3bf69 100644
--- a/remoting/src/main/java/org/apache/rocketmq/remoting/common/RemotingUtil.java
+++ b/remoting/src/main/java/org/apache/rocketmq/remoting/common/RemotingUtil.java
@@ -19,6 +19,7 @@ package org.apache.rocketmq.remoting.common;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
+import java.io.File;
import java.io.IOException;
import java.lang.reflect.Method;
import java.net.Inet6Address;
@@ -98,6 +99,10 @@ public class RemotingUtil {
ArrayList ipv6Result = new ArrayList();
while (enumeration.hasMoreElements()) {
final NetworkInterface networkInterface = enumeration.nextElement();
+ if (isBridge(networkInterface)) {
+ continue;
+ }
+
final Enumeration en = networkInterface.getInetAddresses();
while (en.hasMoreElements()) {
final InetAddress address = en.nextElement();
@@ -160,6 +165,19 @@ public class RemotingUtil {
return sb.toString();
}
+ private static boolean isBridge(NetworkInterface networkInterface) {
+ try {
+ if (isLinuxPlatform()) {
+ String interfaceName = networkInterface.getName();
+ File file = new File("/sys/class/net/" + interfaceName + "/bridge");
+ return file.exists();
+ }
+ } catch (SecurityException e) {
+ //Ignore
+ }
+ return false;
+ }
+
public static SocketChannel connect(SocketAddress remote) {
return connect(remote, 1000 * 5);
}
diff --git a/remoting/src/main/java/org/apache/rocketmq/remoting/netty/NettyRemotingClient.java b/remoting/src/main/java/org/apache/rocketmq/remoting/netty/NettyRemotingClient.java
index d836c8e0bf..5ba6cfab0a 100644
--- a/remoting/src/main/java/org/apache/rocketmq/remoting/netty/NettyRemotingClient.java
+++ b/remoting/src/main/java/org/apache/rocketmq/remoting/netty/NettyRemotingClient.java
@@ -84,7 +84,7 @@ public class NettyRemotingClient extends NettyRemotingAbstract implements Remoti
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();
+ private final Lock namesrvChannelLock = new ReentrantLock();
private final ExecutorService publicExecutor;
@@ -418,7 +418,7 @@ public class NettyRemotingClient extends NettyRemotingAbstract implements Remoti
}
final List addrList = this.namesrvAddrList.get();
- if (this.lockNamesrvChannel.tryLock(LOCK_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS)) {
+ if (this.namesrvChannelLock.tryLock(LOCK_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS)) {
try {
addr = this.namesrvAddrChoosed.get();
if (addr != null) {
@@ -445,7 +445,7 @@ public class NettyRemotingClient extends NettyRemotingAbstract implements Remoti
throw new RemotingConnectException(addrList.toString());
}
} finally {
- this.lockNamesrvChannel.unlock();
+ this.namesrvChannelLock.unlock();
}
} else {
log.warn("getAndCreateNameserverChannel: try to lock name server, but timeout, {}ms", LOCK_TIMEOUT_MILLIS);
diff --git a/remoting/src/main/java/org/apache/rocketmq/remoting/netty/TlsHelper.java b/remoting/src/main/java/org/apache/rocketmq/remoting/netty/TlsHelper.java
index efbdd52c07..5003ce39ef 100644
--- a/remoting/src/main/java/org/apache/rocketmq/remoting/netty/TlsHelper.java
+++ b/remoting/src/main/java/org/apache/rocketmq/remoting/netty/TlsHelper.java
@@ -133,7 +133,7 @@ public class TlsHelper {
SelfSignedCertificate selfSignedCertificate = new SelfSignedCertificate();
return SslContextBuilder
.forServer(selfSignedCertificate.certificate(), selfSignedCertificate.privateKey())
- .sslProvider(SslProvider.JDK)
+ .sslProvider(provider)
.clientAuth(ClientAuth.OPTIONAL)
.build();
} else {
diff --git a/remoting/src/test/java/org/apache/rocketmq/remoting/netty/NettyRemotingAbstractTest.java b/remoting/src/test/java/org/apache/rocketmq/remoting/netty/NettyRemotingAbstractTest.java
index 5330c90060..a272d21da4 100644
--- a/remoting/src/test/java/org/apache/rocketmq/remoting/netty/NettyRemotingAbstractTest.java
+++ b/remoting/src/test/java/org/apache/rocketmq/remoting/netty/NettyRemotingAbstractTest.java
@@ -27,8 +27,6 @@ import org.mockito.junit.MockitoJUnitRunner;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.ArgumentMatchers.notNull;
import static org.mockito.Mockito.when;
@RunWith(MockitoJUnitRunner.class)
@@ -98,7 +96,7 @@ public class NettyRemotingAbstractTest {
public void testScanResponseTable() {
int dummyId = 1;
// mock timeout
- ResponseFuture responseFuture = new ResponseFuture(null,dummyId, -1000, new InvokeCallback() {
+ ResponseFuture responseFuture = new ResponseFuture(null, dummyId, -1000, new InvokeCallback() {
@Override
public void operationComplete(final ResponseFuture responseFuture) {
}
diff --git a/remoting/src/test/java/org/apache/rocketmq/remoting/netty/NettyRemotingClientTest.java b/remoting/src/test/java/org/apache/rocketmq/remoting/netty/NettyRemotingClientTest.java
index 6b5633df1d..4b38ce9524 100644
--- a/remoting/src/test/java/org/apache/rocketmq/remoting/netty/NettyRemotingClientTest.java
+++ b/remoting/src/test/java/org/apache/rocketmq/remoting/netty/NettyRemotingClientTest.java
@@ -16,7 +16,6 @@
*/
package org.apache.rocketmq.remoting.netty;
-import java.lang.reflect.Field;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import org.junit.Test;
diff --git a/srvutil/pom.xml b/srvutil/pom.xml
index 36fe9c03a5..b95808b7c2 100644
--- a/srvutil/pom.xml
+++ b/srvutil/pom.xml
@@ -19,7 +19,7 @@
org.apache.rocketmq
rocketmq-all
- 4.8.0-SNAPSHOT
+ 4.8.1-SNAPSHOT
4.0.0
diff --git a/store/pom.xml b/store/pom.xml
index 8f4b44a288..ed54db1b24 100644
--- a/store/pom.xml
+++ b/store/pom.xml
@@ -19,7 +19,7 @@
org.apache.rocketmq
rocketmq-all
- 4.8.0-SNAPSHOT
+ 4.8.1-SNAPSHOT
4.0.0
@@ -31,7 +31,7 @@
io.openmessaging.storage
dledger
- 0.2.0
+ 0.2.2
org.apache.rocketmq
diff --git a/store/src/main/java/org/apache/rocketmq/store/CommitLog.java b/store/src/main/java/org/apache/rocketmq/store/CommitLog.java
index b6d17daa4e..cce6481b8d 100644
--- a/store/src/main/java/org/apache/rocketmq/store/CommitLog.java
+++ b/store/src/main/java/org/apache/rocketmq/store/CommitLog.java
@@ -661,14 +661,18 @@ public class CommitLog {
storeStatsService.getSinglePutMessageTopicTimesTotal(msg.getTopic()).incrementAndGet();
storeStatsService.getSinglePutMessageTopicSizeTotal(topic).addAndGet(result.getWroteBytes());
- CompletableFuture flushResultFuture = submitFlushRequest(result, putMessageResult, msg);
- CompletableFuture replicaResultFuture = submitReplicaRequest(result, putMessageResult, msg);
+ CompletableFuture flushResultFuture = submitFlushRequest(result, msg);
+ CompletableFuture replicaResultFuture = submitReplicaRequest(result, msg);
return flushResultFuture.thenCombine(replicaResultFuture, (flushStatus, replicaStatus) -> {
if (flushStatus != PutMessageStatus.PUT_OK) {
- putMessageResult.setPutMessageStatus(PutMessageStatus.FLUSH_DISK_TIMEOUT);
+ putMessageResult.setPutMessageStatus(flushStatus);
}
if (replicaStatus != PutMessageStatus.PUT_OK) {
putMessageResult.setPutMessageStatus(replicaStatus);
+ if (replicaStatus == PutMessageStatus.FLUSH_SLAVE_TIMEOUT) {
+ log.error("do sync transfer other node, wait return, but failed, topic: {} tags: {} client address: {}",
+ msg.getTopic(), msg.getTags(), msg.getBornHostNameString());
+ }
}
return putMessageResult;
});
@@ -762,15 +766,18 @@ public class CommitLog {
storeStatsService.getSinglePutMessageTopicTimesTotal(messageExtBatch.getTopic()).addAndGet(result.getMsgNum());
storeStatsService.getSinglePutMessageTopicSizeTotal(messageExtBatch.getTopic()).addAndGet(result.getWroteBytes());
- CompletableFuture flushOKFuture = submitFlushRequest(result, putMessageResult, messageExtBatch);
- CompletableFuture replicaOKFuture = submitReplicaRequest(result, putMessageResult, messageExtBatch);
+ CompletableFuture flushOKFuture = submitFlushRequest(result, messageExtBatch);
+ CompletableFuture replicaOKFuture = submitReplicaRequest(result, messageExtBatch);
return flushOKFuture.thenCombine(replicaOKFuture, (flushStatus, replicaStatus) -> {
if (flushStatus != PutMessageStatus.PUT_OK) {
- putMessageResult.setPutMessageStatus(PutMessageStatus.FLUSH_DISK_TIMEOUT);
+ putMessageResult.setPutMessageStatus(flushStatus);
}
-
if (replicaStatus != PutMessageStatus.PUT_OK) {
putMessageResult.setPutMessageStatus(replicaStatus);
+ if (replicaStatus == PutMessageStatus.FLUSH_SLAVE_TIMEOUT) {
+ log.error("do sync transfer other node, wait return, but failed, topic: {} client address: {}",
+ messageExtBatch.getTopic(), messageExtBatch.getBornHostNameString());
+ }
}
return putMessageResult;
});
@@ -900,8 +907,7 @@ public class CommitLog {
return putMessageResult;
}
- public CompletableFuture submitFlushRequest(AppendMessageResult result, PutMessageResult putMessageResult,
- MessageExt messageExt) {
+ public CompletableFuture submitFlushRequest(AppendMessageResult result, MessageExt messageExt) {
// Synchronization flush
if (FlushDiskType.SYNC_FLUSH == this.defaultMessageStore.getMessageStoreConfig().getFlushDiskType()) {
final GroupCommitService service = (GroupCommitService) this.flushCommitLogService;
@@ -926,8 +932,7 @@ public class CommitLog {
}
}
- public CompletableFuture submitReplicaRequest(AppendMessageResult result, PutMessageResult putMessageResult,
- MessageExt messageExt) {
+ public CompletableFuture submitReplicaRequest(AppendMessageResult result, MessageExt messageExt) {
if (BrokerRole.SYNC_MASTER == this.defaultMessageStore.getMessageStoreConfig().getBrokerRole()) {
HAService service = this.defaultMessageStore.getHaService();
if (messageExt.isWaitStoreMsgOK()) {
@@ -1420,13 +1425,10 @@ public class CommitLog {
for (GroupCommitRequest req : this.requestsRead) {
// There may be a message in the next file, so a maximum of
// two times the flush
- boolean flushOK = false;
+ boolean flushOK = CommitLog.this.mappedFileQueue.getFlushedWhere() >= req.getNextOffset();
for (int i = 0; i < 2 && !flushOK; i++) {
+ CommitLog.this.mappedFileQueue.flush(0);
flushOK = CommitLog.this.mappedFileQueue.getFlushedWhere() >= req.getNextOffset();
-
- if (!flushOK) {
- CommitLog.this.mappedFileQueue.flush(0);
- }
}
req.wakeupCustomer(flushOK ? PutMessageStatus.PUT_OK : PutMessageStatus.FLUSH_DISK_TIMEOUT);
@@ -1795,6 +1797,11 @@ public class CommitLog {
ByteBuffer bornHostHolder = ByteBuffer.allocate(bornHostLength);
ByteBuffer storeHostHolder = ByteBuffer.allocate(storeHostLength);
+ // properties from MessageExtBatch
+ String batchPropStr = MessageDecoder.messageProperties2String(messageExtBatch.getProperties());
+ final byte[] batchPropData = batchPropStr.getBytes(MessageDecoder.CHARSET_UTF8);
+ final short batchPropLen = (short) batchPropData.length;
+
while (messagesByteBuff.hasRemaining()) {
// 1 TOTALSIZE
messagesByteBuff.getInt();
@@ -1818,7 +1825,8 @@ public class CommitLog {
final int topicLength = topicData.length;
- final int msgLen = calMsgLength(messageExtBatch.getSysFlag(), bodyLen, topicLength, propertiesLen);
+ final int msgLen = calMsgLength(messageExtBatch.getSysFlag(), bodyLen, topicLength,
+ propertiesLen + batchPropLen);
// Exceeds the maximum message
if (msgLen > this.maxMessageSize) {
@@ -1871,9 +1879,13 @@ public class CommitLog {
this.msgBatchMemory.put((byte) topicLength);
this.msgBatchMemory.put(topicData);
// 17 PROPERTIES
- this.msgBatchMemory.putShort(propertiesLen);
- if (propertiesLen > 0)
+ this.msgBatchMemory.putShort((short) (propertiesLen + batchPropLen));
+ if (propertiesLen > 0) {
this.msgBatchMemory.put(messagesByteBuff.array(), propertiesPos, propertiesLen);
+ }
+ if (batchPropLen > 0) {
+ this.msgBatchMemory.put(batchPropData, 0, batchPropLen);
+ }
}
msgBatchMemory.flip();
return msgBatchMemory;
diff --git a/store/src/main/java/org/apache/rocketmq/store/DefaultMessageStore.java b/store/src/main/java/org/apache/rocketmq/store/DefaultMessageStore.java
index 5462e76bfb..b8ecdee8cc 100644
--- a/store/src/main/java/org/apache/rocketmq/store/DefaultMessageStore.java
+++ b/store/src/main/java/org/apache/rocketmq/store/DefaultMessageStore.java
@@ -392,7 +392,7 @@ public class DefaultMessageStore implements MessageStore {
if (BrokerRole.SLAVE == this.messageStoreConfig.getBrokerRole()) {
long value = this.printTimes.getAndIncrement();
if ((value % 50000) == 0) {
- log.warn("message store has shutdown, so putMessage is forbidden");
+ log.warn("broke role is slave, so putMessage is forbidden");
}
return PutMessageStatus.SERVICE_NOT_AVAILABLE;
}
@@ -400,7 +400,8 @@ public class DefaultMessageStore implements MessageStore {
if (!this.runningFlags.isWriteable()) {
long value = this.printTimes.getAndIncrement();
if ((value % 50000) == 0) {
- log.warn("message store has shutdown, so putMessage is forbidden");
+ log.warn("the message store is not writable. It may be caused by one of the following reasons: " +
+ "the broker's disk is full, write to logic queue error, write to index file error, etc");
}
return PutMessageStatus.SERVICE_NOT_AVAILABLE;
} else {
@@ -1029,7 +1030,8 @@ public class DefaultMessageStore implements MessageStore {
Entry> next = it.next();
String topic = next.getKey();
- if (!topics.contains(topic) && !topic.equals(TopicValidator.RMQ_SYS_SCHEDULE_TOPIC)) {
+ if (!topics.contains(topic) && !topic.equals(TopicValidator.RMQ_SYS_SCHEDULE_TOPIC)
+ && !topic.equals(TopicValidator.RMQ_SYS_TRANS_OP_HALF_TOPIC)) {
ConcurrentMap queueTable = next.getValue();
for (ConsumeQueue cq : queueTable.values()) {
cq.destroy();
@@ -1745,8 +1747,7 @@ public class DefaultMessageStore implements MessageStore {
this.manualDeleteFileSeveralTimes = manualDeleteFileSeveralTimes;
}
public boolean isSpaceFull() {
- String storePathPhysic = DefaultMessageStore.this.getMessageStoreConfig().getStorePathCommitLog();
- double physicRatio = UtilAll.getDiskPartitionSpaceUsedPercent(storePathPhysic);
+ double physicRatio = UtilAll.getDiskPartitionSpaceUsedPercent(getStorePathPhysic());
double ratio = DefaultMessageStore.this.getMessageStoreConfig().getDiskMaxUsedSpaceRatio() / 100.0;
if (physicRatio > ratio) {
DefaultMessageStore.log.info("physic disk of commitLog used: " + physicRatio);
@@ -1946,7 +1947,8 @@ public class DefaultMessageStore implements MessageStore {
DefaultMessageStore.this.doDispatch(dispatchRequest);
if (BrokerRole.SLAVE != DefaultMessageStore.this.getMessageStoreConfig().getBrokerRole()
- && DefaultMessageStore.this.brokerConfig.isLongPollingEnable()) {
+ && DefaultMessageStore.this.brokerConfig.isLongPollingEnable()
+ && DefaultMessageStore.this.messageArrivingListener != null) {
DefaultMessageStore.this.messageArrivingListener.arriving(dispatchRequest.getTopic(),
dispatchRequest.getQueueId(), dispatchRequest.getConsumeQueueOffset() + 1,
dispatchRequest.getTagsCode(), dispatchRequest.getStoreTimestamp(),
diff --git a/store/src/main/java/org/apache/rocketmq/store/MappedFile.java b/store/src/main/java/org/apache/rocketmq/store/MappedFile.java
index 9185d21d87..b5bdc7766b 100644
--- a/store/src/main/java/org/apache/rocketmq/store/MappedFile.java
+++ b/store/src/main/java/org/apache/rocketmq/store/MappedFile.java
@@ -321,7 +321,7 @@ public class MappedFile extends ReferenceResource {
int writePos = this.wrotePosition.get();
int lastCommittedPosition = this.committedPosition.get();
- if (writePos - this.committedPosition.get() > 0) {
+ if (writePos - lastCommittedPosition > commitLeastPages) {
try {
ByteBuffer byteBuffer = writeBuffer.slice();
byteBuffer.position(lastCommittedPosition);
diff --git a/store/src/main/java/org/apache/rocketmq/store/dledger/DLedgerCommitLog.java b/store/src/main/java/org/apache/rocketmq/store/dledger/DLedgerCommitLog.java
index 400ad786db..9241ffe423 100644
--- a/store/src/main/java/org/apache/rocketmq/store/dledger/DLedgerCommitLog.java
+++ b/store/src/main/java/org/apache/rocketmq/store/dledger/DLedgerCommitLog.java
@@ -17,19 +17,25 @@
package org.apache.rocketmq.store.dledger;
import io.openmessaging.storage.dledger.AppendFuture;
+import io.openmessaging.storage.dledger.BatchAppendFuture;
import io.openmessaging.storage.dledger.DLedgerConfig;
import io.openmessaging.storage.dledger.DLedgerServer;
import io.openmessaging.storage.dledger.entry.DLedgerEntry;
import io.openmessaging.storage.dledger.protocol.AppendEntryRequest;
import io.openmessaging.storage.dledger.protocol.AppendEntryResponse;
+import io.openmessaging.storage.dledger.protocol.BatchAppendEntryRequest;
import io.openmessaging.storage.dledger.protocol.DLedgerResponseCode;
import io.openmessaging.storage.dledger.store.file.DLedgerMmapFileStore;
import io.openmessaging.storage.dledger.store.file.MmapFile;
import io.openmessaging.storage.dledger.store.file.MmapFileList;
import io.openmessaging.storage.dledger.store.file.SelectMmapBufferResult;
import io.openmessaging.storage.dledger.utils.DLedgerUtils;
+import java.net.Inet6Address;
+import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import org.apache.rocketmq.common.UtilAll;
@@ -72,6 +78,8 @@ public class DLedgerCommitLog extends CommitLog {
private boolean isInrecoveringOldCommitlog = false;
+ private final StringBuilder msgIdBuilder = new StringBuilder();
+
public DLedgerCommitLog(final DefaultMessageStore defaultMessageStore) {
super(defaultMessageStore);
dLedgerConfig = new DLedgerConfig();
@@ -364,21 +372,14 @@ public class DLedgerCommitLog extends CommitLog {
return beginTimeInDledgerLock;
}
- @Override
- public PutMessageResult putMessage(final MessageExtBrokerInner msg) {
+ private void setMessageInfo(MessageExtBrokerInner msg, int tranType) {
// Set the storage time
msg.setStoreTimestamp(System.currentTimeMillis());
// Set the message body BODY CRC (consider the most appropriate setting
// on the client)
msg.setBodyCRC(UtilAll.crc32(msg.getBody()));
- StoreStatsService storeStatsService = this.defaultMessageStore.getStoreStatsService();
-
- String topic = msg.getTopic();
- int queueId = msg.getQueueId();
-
//should be consistent with the old version
- final int tranType = MessageSysFlag.getTransactionValue(msg.getSysFlag());
if (tranType == MessageSysFlag.TRANSACTION_NOT_TYPE
|| tranType == MessageSysFlag.TRANSACTION_COMMIT_TYPE) {
// Delay Delivery
@@ -387,8 +388,9 @@ public class DLedgerCommitLog extends CommitLog {
msg.setDelayTimeLevel(this.defaultMessageStore.getScheduleMessageService().getMaxDelayLevel());
}
- topic = TopicValidator.RMQ_SYS_SCHEDULE_TOPIC;
- queueId = ScheduleMessageService.delayLevel2QueueId(msg.getDelayTimeLevel());
+
+ String topic = TopicValidator.RMQ_SYS_SCHEDULE_TOPIC;
+ int queueId = ScheduleMessageService.delayLevel2QueueId(msg.getDelayTimeLevel());
// Backup real topic, queueId
MessageAccessor.putProperty(msg, MessageConst.PROPERTY_REAL_TOPIC, msg.getTopic());
@@ -400,25 +402,46 @@ public class DLedgerCommitLog extends CommitLog {
}
}
+ InetSocketAddress bornSocketAddress = (InetSocketAddress) msg.getBornHost();
+ if (bornSocketAddress.getAddress() instanceof Inet6Address) {
+ msg.setBornHostV6Flag();
+ }
+
+ InetSocketAddress storeSocketAddress = (InetSocketAddress) msg.getStoreHost();
+ if (storeSocketAddress.getAddress() instanceof Inet6Address) {
+ msg.setStoreHostAddressV6Flag();
+ }
+ }
+
+ @Override
+ public PutMessageResult putMessage(final MessageExtBrokerInner msg) {
+
+ StoreStatsService storeStatsService = this.defaultMessageStore.getStoreStatsService();
+ final int tranType = MessageSysFlag.getTransactionValue(msg.getSysFlag());
+ String topic = msg.getTopic();
+ setMessageInfo(msg,tranType);
+
// Back to Results
AppendMessageResult appendResult;
AppendFuture dledgerFuture;
EncodeResult encodeResult;
+ encodeResult = this.messageSerializer.serialize(msg);
+ if (encodeResult.status != AppendMessageStatus.PUT_OK) {
+ return new PutMessageResult(PutMessageStatus.MESSAGE_ILLEGAL, new AppendMessageResult(encodeResult.status));
+ }
+
putMessageLock.lock(); //spin or ReentrantLock ,depending on store config
long elapsedTimeInLock;
long queueOffset;
try {
beginTimeInDledgerLock = this.defaultMessageStore.getSystemClock().now();
- encodeResult = this.messageSerializer.serialize(msg);
- queueOffset = topicQueueTable.get(encodeResult.queueOffsetKey);
- if (encodeResult.status != AppendMessageStatus.PUT_OK) {
- return new PutMessageResult(PutMessageStatus.MESSAGE_ILLEGAL, new AppendMessageResult(encodeResult.status));
- }
+ queueOffset = getQueueOffsetByKey(encodeResult.queueOffsetKey, tranType);
+ encodeResult.setQueueOffsetKey(queueOffset, false);
AppendEntryRequest request = new AppendEntryRequest();
request.setGroup(dLedgerConfig.getGroup());
request.setRemoteId(dLedgerServer.getMemberState().getSelfId());
- request.setBody(encodeResult.data);
+ request.setBody(encodeResult.getData());
dledgerFuture = (AppendFuture) dLedgerServer.handleAppend(request);
if (dledgerFuture.getPos() == -1) {
return new PutMessageResult(PutMessageStatus.OS_PAGECACHE_BUSY, new AppendMessageResult(AppendMessageStatus.UNKNOWN_ERROR));
@@ -430,7 +453,7 @@ public class DLedgerCommitLog extends CommitLog {
String msgId = MessageDecoder.createMessageId(buffer, msg.getStoreHostBytes(), wroteOffset);
elapsedTimeInLock = this.defaultMessageStore.getSystemClock().now() - beginTimeInDledgerLock;
- appendResult = new AppendMessageResult(AppendMessageStatus.PUT_OK, wroteOffset, encodeResult.data.length, msgId, System.currentTimeMillis(), queueOffset, elapsedTimeInLock);
+ appendResult = new AppendMessageResult(AppendMessageStatus.PUT_OK, wroteOffset, encodeResult.getData().length, msgId, System.currentTimeMillis(), queueOffset, elapsedTimeInLock);
switch (tranType) {
case MessageSysFlag.TRANSACTION_PREPARED_TYPE:
case MessageSysFlag.TRANSACTION_ROLLBACK_TYPE:
@@ -491,17 +514,352 @@ public class DLedgerCommitLog extends CommitLog {
@Override
public PutMessageResult putMessages(final MessageExtBatch messageExtBatch) {
- return new PutMessageResult(PutMessageStatus.MESSAGE_ILLEGAL, null);
+ final int tranType = MessageSysFlag.getTransactionValue(messageExtBatch.getSysFlag());
+
+ if (tranType != MessageSysFlag.TRANSACTION_NOT_TYPE) {
+ return new PutMessageResult(PutMessageStatus.MESSAGE_ILLEGAL, null);
+ }
+ if (messageExtBatch.getDelayTimeLevel() > 0) {
+ return new PutMessageResult(PutMessageStatus.MESSAGE_ILLEGAL, null);
+ }
+
+ // Set the storage time
+ messageExtBatch.setStoreTimestamp(System.currentTimeMillis());
+
+ StoreStatsService storeStatsService = this.defaultMessageStore.getStoreStatsService();
+
+ InetSocketAddress bornSocketAddress = (InetSocketAddress) messageExtBatch.getBornHost();
+ if (bornSocketAddress.getAddress() instanceof Inet6Address) {
+ messageExtBatch.setBornHostV6Flag();
+ }
+
+ InetSocketAddress storeSocketAddress = (InetSocketAddress) messageExtBatch.getStoreHost();
+ if (storeSocketAddress.getAddress() instanceof Inet6Address) {
+ messageExtBatch.setStoreHostAddressV6Flag();
+ }
+
+ // Back to Results
+ AppendMessageResult appendResult;
+ BatchAppendFuture dledgerFuture;
+ EncodeResult encodeResult;
+
+ encodeResult = this.messageSerializer.serialize(messageExtBatch);
+ if (encodeResult.status != AppendMessageStatus.PUT_OK) {
+ return new PutMessageResult(PutMessageStatus.MESSAGE_ILLEGAL, new AppendMessageResult(encodeResult
+ .status));
+ }
+
+ putMessageLock.lock(); //spin or ReentrantLock ,depending on store config
+ msgIdBuilder.setLength(0);
+ long elapsedTimeInLock;
+ long queueOffset;
+ long msgNum = 0;
+ try {
+ beginTimeInDledgerLock = this.defaultMessageStore.getSystemClock().now();
+ queueOffset = getQueueOffsetByKey(encodeResult.queueOffsetKey, tranType);
+ encodeResult.setQueueOffsetKey(queueOffset, true);
+ BatchAppendEntryRequest request = new BatchAppendEntryRequest();
+ request.setGroup(dLedgerConfig.getGroup());
+ request.setRemoteId(dLedgerServer.getMemberState().getSelfId());
+ request.setBatchMsgs(encodeResult.batchData);
+ dledgerFuture = (BatchAppendFuture) dLedgerServer.handleAppend(request);
+ if (dledgerFuture.getPos() == -1) {
+ log.warn("HandleAppend return false due to error code {}", dledgerFuture.get().getCode());
+ return new PutMessageResult(PutMessageStatus.OS_PAGECACHE_BUSY, new AppendMessageResult(AppendMessageStatus.UNKNOWN_ERROR));
+ }
+ long wroteOffset = 0;
+
+ int msgIdLength = (messageExtBatch.getSysFlag() & MessageSysFlag.STOREHOSTADDRESS_V6_FLAG) == 0 ? 4 + 4 + 8 : 16 + 4 + 8;
+ ByteBuffer buffer = ByteBuffer.allocate(msgIdLength);
+
+ boolean isFirstOffset = true;
+ long firstWroteOffset = 0;
+ for (long pos : dledgerFuture.getPositions()) {
+ wroteOffset = pos + DLedgerEntry.BODY_OFFSET;
+ if (isFirstOffset) {
+ firstWroteOffset = wroteOffset;
+ isFirstOffset = false;
+ }
+ String msgId = MessageDecoder.createMessageId(buffer, messageExtBatch.getStoreHostBytes(), wroteOffset);
+ if (msgIdBuilder.length() > 0) {
+ msgIdBuilder.append(',').append(msgId);
+ } else {
+ msgIdBuilder.append(msgId);
+ }
+ msgNum++;
+ }
+
+ elapsedTimeInLock = this.defaultMessageStore.getSystemClock().now() - beginTimeInDledgerLock;
+ appendResult = new AppendMessageResult(AppendMessageStatus.PUT_OK, firstWroteOffset, encodeResult.totalMsgLen,
+ msgIdBuilder.toString(), System.currentTimeMillis(), queueOffset, elapsedTimeInLock);
+ DLedgerCommitLog.this.topicQueueTable.put(encodeResult.queueOffsetKey, queueOffset + msgNum);
+ } catch (Exception e) {
+ log.error("Put message error", e);
+ return new PutMessageResult(PutMessageStatus.UNKNOWN_ERROR, new AppendMessageResult(AppendMessageStatus
+ .UNKNOWN_ERROR));
+ } finally {
+ beginTimeInDledgerLock = 0;
+ putMessageLock.unlock();
+ }
+
+ if (elapsedTimeInLock > 500) {
+ log.warn("[NOTIFYME]putMessage in lock cost time(ms)={}, bodyLength={} AppendMessageResult={}",
+ elapsedTimeInLock, messageExtBatch.getBody().length, appendResult);
+ }
+
+ PutMessageStatus putMessageStatus = PutMessageStatus.UNKNOWN_ERROR;
+ try {
+ AppendEntryResponse appendEntryResponse = dledgerFuture.get(3, TimeUnit.SECONDS);
+ switch (DLedgerResponseCode.valueOf(appendEntryResponse.getCode())) {
+ case SUCCESS:
+ putMessageStatus = PutMessageStatus.PUT_OK;
+ break;
+ case INCONSISTENT_LEADER:
+ case NOT_LEADER:
+ case LEADER_NOT_READY:
+ case DISK_FULL:
+ putMessageStatus = PutMessageStatus.SERVICE_NOT_AVAILABLE;
+ break;
+ case WAIT_QUORUM_ACK_TIMEOUT:
+ //Do not return flush_slave_timeout to the client, for the ons client will ignore it.
+ putMessageStatus = PutMessageStatus.OS_PAGECACHE_BUSY;
+ break;
+ case LEADER_PENDING_FULL:
+ putMessageStatus = PutMessageStatus.OS_PAGECACHE_BUSY;
+ break;
+ }
+ } catch (Throwable t) {
+ log.error("Failed to get dledger append result", t);
+ }
+
+ PutMessageResult putMessageResult = new PutMessageResult(putMessageStatus, appendResult);
+ if (putMessageStatus == PutMessageStatus.PUT_OK) {
+ // Statistics
+ storeStatsService.getSinglePutMessageTopicTimesTotal(messageExtBatch.getTopic()).addAndGet(msgNum);
+ storeStatsService.getSinglePutMessageTopicSizeTotal(messageExtBatch.getTopic()).addAndGet(encodeResult.totalMsgLen);
+ }
+ return putMessageResult;
}
@Override
public CompletableFuture asyncPutMessage(MessageExtBrokerInner msg) {
- return CompletableFuture.completedFuture(this.putMessage(msg));
+
+ StoreStatsService storeStatsService = this.defaultMessageStore.getStoreStatsService();
+
+ final int tranType = MessageSysFlag.getTransactionValue(msg.getSysFlag());
+
+ setMessageInfo(msg, tranType);
+
+ final String finalTopic = msg.getTopic();
+
+ // Back to Results
+ AppendMessageResult appendResult;
+ AppendFuture dledgerFuture;
+ EncodeResult encodeResult;
+
+ encodeResult = this.messageSerializer.serialize(msg);
+ if (encodeResult.status != AppendMessageStatus.PUT_OK) {
+ return CompletableFuture.completedFuture(new PutMessageResult(PutMessageStatus.MESSAGE_ILLEGAL, new AppendMessageResult(encodeResult.status)));
+ }
+ putMessageLock.lock(); //spin or ReentrantLock ,depending on store config
+ long elapsedTimeInLock;
+ long queueOffset;
+ try {
+ beginTimeInDledgerLock = this.defaultMessageStore.getSystemClock().now();
+ queueOffset = getQueueOffsetByKey(encodeResult.queueOffsetKey, tranType);
+ encodeResult.setQueueOffsetKey(queueOffset, false);
+ AppendEntryRequest request = new AppendEntryRequest();
+ request.setGroup(dLedgerConfig.getGroup());
+ request.setRemoteId(dLedgerServer.getMemberState().getSelfId());
+ request.setBody(encodeResult.getData());
+ dledgerFuture = (AppendFuture) dLedgerServer.handleAppend(request);
+ if (dledgerFuture.getPos() == -1) {
+ return CompletableFuture.completedFuture(new PutMessageResult(PutMessageStatus.OS_PAGECACHE_BUSY, new AppendMessageResult(AppendMessageStatus.UNKNOWN_ERROR)));
+ }
+ long wroteOffset = dledgerFuture.getPos() + DLedgerEntry.BODY_OFFSET;
+
+ int msgIdLength = (msg.getSysFlag() & MessageSysFlag.STOREHOSTADDRESS_V6_FLAG) == 0 ? 4 + 4 + 8 : 16 + 4 + 8;
+ ByteBuffer buffer = ByteBuffer.allocate(msgIdLength);
+
+ String msgId = MessageDecoder.createMessageId(buffer, msg.getStoreHostBytes(), wroteOffset);
+ elapsedTimeInLock = this.defaultMessageStore.getSystemClock().now() - beginTimeInDledgerLock;
+ appendResult = new AppendMessageResult(AppendMessageStatus.PUT_OK, wroteOffset, encodeResult.getData().length, msgId, System.currentTimeMillis(), queueOffset, elapsedTimeInLock);
+ switch (tranType) {
+ case MessageSysFlag.TRANSACTION_PREPARED_TYPE:
+ case MessageSysFlag.TRANSACTION_ROLLBACK_TYPE:
+ break;
+ case MessageSysFlag.TRANSACTION_NOT_TYPE:
+ case MessageSysFlag.TRANSACTION_COMMIT_TYPE:
+ // The next update ConsumeQueue information
+ DLedgerCommitLog.this.topicQueueTable.put(encodeResult.queueOffsetKey, queueOffset + 1);
+ break;
+ default:
+ break;
+ }
+ } catch (Exception e) {
+ log.error("Put message error", e);
+ return CompletableFuture.completedFuture(new PutMessageResult(PutMessageStatus.UNKNOWN_ERROR, new AppendMessageResult(AppendMessageStatus.UNKNOWN_ERROR)));
+ } finally {
+ beginTimeInDledgerLock = 0;
+ putMessageLock.unlock();
+ }
+
+ if (elapsedTimeInLock > 500) {
+ log.warn("[NOTIFYME]putMessage in lock cost time(ms)={}, bodyLength={} AppendMessageResult={}", elapsedTimeInLock, msg.getBody().length, appendResult);
+ }
+
+ return dledgerFuture.thenApply(appendEntryResponse -> {
+ PutMessageStatus putMessageStatus = PutMessageStatus.UNKNOWN_ERROR;
+ switch (DLedgerResponseCode.valueOf(appendEntryResponse.getCode())) {
+ case SUCCESS:
+ putMessageStatus = PutMessageStatus.PUT_OK;
+ break;
+ case INCONSISTENT_LEADER:
+ case NOT_LEADER:
+ case LEADER_NOT_READY:
+ case DISK_FULL:
+ putMessageStatus = PutMessageStatus.SERVICE_NOT_AVAILABLE;
+ break;
+ case WAIT_QUORUM_ACK_TIMEOUT:
+ //Do not return flush_slave_timeout to the client, for the ons client will ignore it.
+ putMessageStatus = PutMessageStatus.OS_PAGECACHE_BUSY;
+ break;
+ case LEADER_PENDING_FULL:
+ putMessageStatus = PutMessageStatus.OS_PAGECACHE_BUSY;
+ break;
+ }
+ PutMessageResult putMessageResult = new PutMessageResult(putMessageStatus, appendResult);
+ if (putMessageStatus == PutMessageStatus.PUT_OK) {
+ // Statistics
+ storeStatsService.getSinglePutMessageTopicTimesTotal(finalTopic).incrementAndGet();
+ storeStatsService.getSinglePutMessageTopicSizeTotal(msg.getTopic()).addAndGet(appendResult.getWroteBytes());
+ }
+ return putMessageResult;
+ });
}
@Override
public CompletableFuture asyncPutMessages(MessageExtBatch messageExtBatch) {
- return CompletableFuture.completedFuture(putMessages(messageExtBatch));
+ final int tranType = MessageSysFlag.getTransactionValue(messageExtBatch.getSysFlag());
+
+ if (tranType != MessageSysFlag.TRANSACTION_NOT_TYPE) {
+ return CompletableFuture.completedFuture(new PutMessageResult(PutMessageStatus.MESSAGE_ILLEGAL, null));
+ }
+ if (messageExtBatch.getDelayTimeLevel() > 0) {
+ return CompletableFuture.completedFuture(new PutMessageResult(PutMessageStatus.MESSAGE_ILLEGAL, null));
+ }
+
+ // Set the storage time
+ messageExtBatch.setStoreTimestamp(System.currentTimeMillis());
+
+ StoreStatsService storeStatsService = this.defaultMessageStore.getStoreStatsService();
+
+ InetSocketAddress bornSocketAddress = (InetSocketAddress) messageExtBatch.getBornHost();
+ if (bornSocketAddress.getAddress() instanceof Inet6Address) {
+ messageExtBatch.setBornHostV6Flag();
+ }
+
+ InetSocketAddress storeSocketAddress = (InetSocketAddress) messageExtBatch.getStoreHost();
+ if (storeSocketAddress.getAddress() instanceof Inet6Address) {
+ messageExtBatch.setStoreHostAddressV6Flag();
+ }
+
+ // Back to Results
+ AppendMessageResult appendResult;
+ BatchAppendFuture dledgerFuture;
+ EncodeResult encodeResult;
+
+ encodeResult = this.messageSerializer.serialize(messageExtBatch);
+ if (encodeResult.status != AppendMessageStatus.PUT_OK) {
+ return CompletableFuture.completedFuture(new PutMessageResult(PutMessageStatus.MESSAGE_ILLEGAL, new AppendMessageResult(encodeResult
+ .status)));
+ }
+
+ putMessageLock.lock(); //spin or ReentrantLock ,depending on store config
+ msgIdBuilder.setLength(0);
+ long elapsedTimeInLock;
+ long queueOffset;
+ long msgNum = 0;
+ try {
+ beginTimeInDledgerLock = this.defaultMessageStore.getSystemClock().now();
+ queueOffset = getQueueOffsetByKey(encodeResult.queueOffsetKey, tranType);
+ encodeResult.setQueueOffsetKey(queueOffset, true);
+ BatchAppendEntryRequest request = new BatchAppendEntryRequest();
+ request.setGroup(dLedgerConfig.getGroup());
+ request.setRemoteId(dLedgerServer.getMemberState().getSelfId());
+ request.setBatchMsgs(encodeResult.batchData);
+ dledgerFuture = (BatchAppendFuture) dLedgerServer.handleAppend(request);
+ if (dledgerFuture.getPos() == -1) {
+ log.warn("HandleAppend return false due to error code {}", dledgerFuture.get().getCode());
+ return CompletableFuture.completedFuture(new PutMessageResult(PutMessageStatus.OS_PAGECACHE_BUSY, new AppendMessageResult(AppendMessageStatus.UNKNOWN_ERROR)));
+ }
+ long wroteOffset = 0;
+
+ int msgIdLength = (messageExtBatch.getSysFlag() & MessageSysFlag.STOREHOSTADDRESS_V6_FLAG) == 0 ? 4 + 4 + 8 : 16 + 4 + 8;
+ ByteBuffer buffer = ByteBuffer.allocate(msgIdLength);
+
+ boolean isFirstOffset = true;
+ long firstWroteOffset = 0;
+ for (long pos : dledgerFuture.getPositions()) {
+ wroteOffset = pos + DLedgerEntry.BODY_OFFSET;
+ if (isFirstOffset) {
+ firstWroteOffset = wroteOffset;
+ isFirstOffset = false;
+ }
+ String msgId = MessageDecoder.createMessageId(buffer, messageExtBatch.getStoreHostBytes(), wroteOffset);
+ if (msgIdBuilder.length() > 0) {
+ msgIdBuilder.append(',').append(msgId);
+ } else {
+ msgIdBuilder.append(msgId);
+ }
+ msgNum++;
+ }
+
+ elapsedTimeInLock = this.defaultMessageStore.getSystemClock().now() - beginTimeInDledgerLock;
+ appendResult = new AppendMessageResult(AppendMessageStatus.PUT_OK, firstWroteOffset, encodeResult.totalMsgLen,
+ msgIdBuilder.toString(), System.currentTimeMillis(), queueOffset, elapsedTimeInLock);
+ DLedgerCommitLog.this.topicQueueTable.put(encodeResult.queueOffsetKey, queueOffset + msgNum);
+ } catch (Exception e) {
+ log.error("Put message error", e);
+ return CompletableFuture.completedFuture(new PutMessageResult(PutMessageStatus.UNKNOWN_ERROR, new AppendMessageResult(AppendMessageStatus.UNKNOWN_ERROR)));
+ } finally {
+ beginTimeInDledgerLock = 0;
+ putMessageLock.unlock();
+ }
+
+ if (elapsedTimeInLock > 500) {
+ log.warn("[NOTIFYME]putMessage in lock cost time(ms)={}, bodyLength={} AppendMessageResult={}",
+ elapsedTimeInLock, messageExtBatch.getBody().length, appendResult);
+ }
+
+ return dledgerFuture.thenApply(appendEntryResponse -> {
+ PutMessageStatus putMessageStatus = PutMessageStatus.UNKNOWN_ERROR;
+ switch (DLedgerResponseCode.valueOf(appendEntryResponse.getCode())) {
+ case SUCCESS:
+ putMessageStatus = PutMessageStatus.PUT_OK;
+ break;
+ case INCONSISTENT_LEADER:
+ case NOT_LEADER:
+ case LEADER_NOT_READY:
+ case DISK_FULL:
+ putMessageStatus = PutMessageStatus.SERVICE_NOT_AVAILABLE;
+ break;
+ case WAIT_QUORUM_ACK_TIMEOUT:
+ //Do not return flush_slave_timeout to the client, for the ons client will ignore it.
+ putMessageStatus = PutMessageStatus.OS_PAGECACHE_BUSY;
+ break;
+ case LEADER_PENDING_FULL:
+ putMessageStatus = PutMessageStatus.OS_PAGECACHE_BUSY;
+ break;
+ }
+ PutMessageResult putMessageResult = new PutMessageResult(putMessageStatus, appendResult);
+ if (putMessageStatus == PutMessageStatus.PUT_OK) {
+ // Statistics
+ storeStatsService.getSinglePutMessageTopicTimesTotal(messageExtBatch.getTopic()).incrementAndGet();
+ storeStatsService.getSinglePutMessageTopicSizeTotal(messageExtBatch.getTopic()).addAndGet(appendResult.getWroteBytes());
+ }
+ return putMessageResult;
+ });
}
@Override
@@ -566,51 +924,83 @@ public class DLedgerCommitLog extends CommitLog {
return diff;
}
+ private long getQueueOffsetByKey(String key, int tranType) {
+ Long queueOffset = DLedgerCommitLog.this.topicQueueTable.get(key);
+ if (null == queueOffset) {
+ queueOffset = 0L;
+ DLedgerCommitLog.this.topicQueueTable.put(key, queueOffset);
+ }
+
+ // Transaction messages that require special handling
+ switch (tranType) {
+ // Prepared and Rollback message is not consumed, will not enter the
+ // consumer queuec
+ case MessageSysFlag.TRANSACTION_PREPARED_TYPE:
+ case MessageSysFlag.TRANSACTION_ROLLBACK_TYPE:
+ queueOffset = 0L;
+ break;
+ case MessageSysFlag.TRANSACTION_NOT_TYPE:
+ case MessageSysFlag.TRANSACTION_COMMIT_TYPE:
+ default:
+ break;
+ }
+ return queueOffset;
+ }
+
+
class EncodeResult {
private String queueOffsetKey;
- private byte[] data;
+ private ByteBuffer data;
+ private List batchData;
private AppendMessageStatus status;
+ private int totalMsgLen;
- public EncodeResult(AppendMessageStatus status, byte[] data, String queueOffsetKey) {
+ public EncodeResult(AppendMessageStatus status, ByteBuffer data, String queueOffsetKey) {
this.data = data;
this.status = status;
this.queueOffsetKey = queueOffsetKey;
}
+
+ public void setQueueOffsetKey(long offset, boolean isBatch) {
+ if (!isBatch) {
+ this.data.putLong(MessageDecoder.QUEUE_OFFSET_POSITION, offset);
+ return;
+ }
+
+ for (byte[] data : batchData) {
+ ByteBuffer.wrap(data).putLong(MessageDecoder.QUEUE_OFFSET_POSITION, offset++);
+ }
+ }
+
+ public byte[] getData() {
+ return data.array();
+ }
+
+ public EncodeResult(AppendMessageStatus status, String queueOffsetKey, List batchData, int totalMsgLen) {
+ this.batchData = batchData;
+ this.status = status;
+ this.queueOffsetKey = queueOffsetKey;
+ this.totalMsgLen = totalMsgLen;
+ }
}
class MessageSerializer {
- // File at the end of the minimum fixed length empty
- private static final int END_FILE_MIN_BLANK_LENGTH = 4 + 4;
- private final ByteBuffer msgIdMemory;
- private final ByteBuffer msgIdV6Memory;
- // Store the message content
- private final ByteBuffer msgStoreItemMemory;
+
// The maximum length of the message
private final int maxMessageSize;
- // Build Message Key
- private final StringBuilder keyBuilder = new StringBuilder();
-
- private final StringBuilder msgIdBuilder = new StringBuilder();
-
-// private final ByteBuffer hostHolder = ByteBuffer.allocate(8);
MessageSerializer(final int size) {
- this.msgIdMemory = ByteBuffer.allocate(4 + 4 + 8);
- this.msgIdV6Memory = ByteBuffer.allocate(16 + 4 + 8);
- this.msgStoreItemMemory = ByteBuffer.allocate(size + END_FILE_MIN_BLANK_LENGTH);
this.maxMessageSize = size;
}
- public ByteBuffer getMsgStoreItemMemory() {
- return msgStoreItemMemory;
- }
-
public EncodeResult serialize(final MessageExtBrokerInner msgInner) {
// STORETIMESTAMP + STOREHOSTADDRESS + OFFSET
// PHY OFFSET
long wroteOffset = 0;
+ long queueOffset = 0;
+
int sysflag = msgInner.getSysFlag();
int bornHostLength = (sysflag & MessageSysFlag.BORNHOST_V6_FLAG) == 0 ? 4 + 4 : 16 + 4;
@@ -618,33 +1008,7 @@ public class DLedgerCommitLog extends CommitLog {
ByteBuffer bornHostHolder = ByteBuffer.allocate(bornHostLength);
ByteBuffer storeHostHolder = ByteBuffer.allocate(storeHostLength);
- // Record ConsumeQueue information
- keyBuilder.setLength(0);
- keyBuilder.append(msgInner.getTopic());
- keyBuilder.append('-');
- keyBuilder.append(msgInner.getQueueId());
- String key = keyBuilder.toString();
-
- Long queueOffset = DLedgerCommitLog.this.topicQueueTable.get(key);
- if (null == queueOffset) {
- queueOffset = 0L;
- DLedgerCommitLog.this.topicQueueTable.put(key, queueOffset);
- }
-
- // Transaction messages that require special handling
- final int tranType = MessageSysFlag.getTransactionValue(msgInner.getSysFlag());
- switch (tranType) {
- // Prepared and Rollback message is not consumed, will not enter the
- // consumer queuec
- case MessageSysFlag.TRANSACTION_PREPARED_TYPE:
- case MessageSysFlag.TRANSACTION_ROLLBACK_TYPE:
- queueOffset = 0L;
- break;
- case MessageSysFlag.TRANSACTION_NOT_TYPE:
- case MessageSysFlag.TRANSACTION_COMMIT_TYPE:
- default:
- break;
- }
+ String key = msgInner.getTopic() + "-" + msgInner.getQueueId();
/**
* Serialize message
@@ -666,6 +1030,8 @@ public class DLedgerCommitLog extends CommitLog {
final int msgLen = calMsgLength(msgInner.getSysFlag(), bodyLength, topicLength, propertiesLength);
+ ByteBuffer msgStoreItemMemory = ByteBuffer.allocate(msgLen);
+
// Exceeds the maximum message
if (msgLen > this.maxMessageSize) {
DLedgerCommitLog.log.warn("message size exceeded, msg total size: " + msgLen + ", msg body size: " + bodyLength
@@ -675,60 +1041,163 @@ public class DLedgerCommitLog extends CommitLog {
// Initialization of storage space
this.resetByteBuffer(msgStoreItemMemory, msgLen);
// 1 TOTALSIZE
- this.msgStoreItemMemory.putInt(msgLen);
+ msgStoreItemMemory.putInt(msgLen);
// 2 MAGICCODE
- this.msgStoreItemMemory.putInt(DLedgerCommitLog.MESSAGE_MAGIC_CODE);
+ msgStoreItemMemory.putInt(DLedgerCommitLog.MESSAGE_MAGIC_CODE);
// 3 BODYCRC
- this.msgStoreItemMemory.putInt(msgInner.getBodyCRC());
+ msgStoreItemMemory.putInt(msgInner.getBodyCRC());
// 4 QUEUEID
- this.msgStoreItemMemory.putInt(msgInner.getQueueId());
+ msgStoreItemMemory.putInt(msgInner.getQueueId());
// 5 FLAG
- this.msgStoreItemMemory.putInt(msgInner.getFlag());
+ msgStoreItemMemory.putInt(msgInner.getFlag());
// 6 QUEUEOFFSET
- this.msgStoreItemMemory.putLong(queueOffset);
+ msgStoreItemMemory.putLong(queueOffset);
// 7 PHYSICALOFFSET
- this.msgStoreItemMemory.putLong(wroteOffset);
+ msgStoreItemMemory.putLong(wroteOffset);
// 8 SYSFLAG
- this.msgStoreItemMemory.putInt(msgInner.getSysFlag());
+ msgStoreItemMemory.putInt(msgInner.getSysFlag());
// 9 BORNTIMESTAMP
- this.msgStoreItemMemory.putLong(msgInner.getBornTimestamp());
+ msgStoreItemMemory.putLong(msgInner.getBornTimestamp());
// 10 BORNHOST
- this.resetByteBuffer(bornHostHolder, bornHostLength);
- this.msgStoreItemMemory.put(msgInner.getBornHostBytes(bornHostHolder));
+ resetByteBuffer(bornHostHolder, bornHostLength);
+ msgStoreItemMemory.put(msgInner.getBornHostBytes(bornHostHolder));
// 11 STORETIMESTAMP
- this.msgStoreItemMemory.putLong(msgInner.getStoreTimestamp());
+ msgStoreItemMemory.putLong(msgInner.getStoreTimestamp());
// 12 STOREHOSTADDRESS
- this.resetByteBuffer(storeHostHolder, storeHostLength);
- this.msgStoreItemMemory.put(msgInner.getStoreHostBytes(storeHostHolder));
+ resetByteBuffer(storeHostHolder, storeHostLength);
+ msgStoreItemMemory.put(msgInner.getStoreHostBytes(storeHostHolder));
//this.msgBatchMemory.put(msgInner.getStoreHostBytes());
// 13 RECONSUMETIMES
- this.msgStoreItemMemory.putInt(msgInner.getReconsumeTimes());
+ msgStoreItemMemory.putInt(msgInner.getReconsumeTimes());
// 14 Prepared Transaction Offset
- this.msgStoreItemMemory.putLong(msgInner.getPreparedTransactionOffset());
+ msgStoreItemMemory.putLong(msgInner.getPreparedTransactionOffset());
// 15 BODY
- this.msgStoreItemMemory.putInt(bodyLength);
+ msgStoreItemMemory.putInt(bodyLength);
if (bodyLength > 0) {
- this.msgStoreItemMemory.put(msgInner.getBody());
+ msgStoreItemMemory.put(msgInner.getBody());
}
// 16 TOPIC
- this.msgStoreItemMemory.put((byte) topicLength);
- this.msgStoreItemMemory.put(topicData);
+ msgStoreItemMemory.put((byte) topicLength);
+ msgStoreItemMemory.put(topicData);
// 17 PROPERTIES
- this.msgStoreItemMemory.putShort((short) propertiesLength);
+ msgStoreItemMemory.putShort((short) propertiesLength);
if (propertiesLength > 0) {
- this.msgStoreItemMemory.put(propertiesData);
+ msgStoreItemMemory.put(propertiesData);
}
- byte[] data = new byte[msgLen];
- this.msgStoreItemMemory.clear();
- this.msgStoreItemMemory.get(data);
- return new EncodeResult(AppendMessageStatus.PUT_OK, data, key);
+ return new EncodeResult(AppendMessageStatus.PUT_OK, msgStoreItemMemory, key);
+ }
+
+ public EncodeResult serialize(final MessageExtBatch messageExtBatch) {
+ String key = messageExtBatch.getTopic() + "-" + messageExtBatch.getQueueId();
+
+ int totalMsgLen = 0;
+ ByteBuffer messagesByteBuff = messageExtBatch.wrap();
+ List batchBody = new LinkedList<>();
+
+ int sysFlag = messageExtBatch.getSysFlag();
+ int bornHostLength = (sysFlag & MessageSysFlag.BORNHOST_V6_FLAG) == 0 ? 4 + 4 : 16 + 4;
+ int storeHostLength = (sysFlag & MessageSysFlag.STOREHOSTADDRESS_V6_FLAG) == 0 ? 4 + 4 : 16 + 4;
+ ByteBuffer bornHostHolder = ByteBuffer.allocate(bornHostLength);
+ ByteBuffer storeHostHolder = ByteBuffer.allocate(storeHostLength);
+
+ while (messagesByteBuff.hasRemaining()) {
+ // 1 TOTALSIZE
+ messagesByteBuff.getInt();
+ // 2 MAGICCODE
+ messagesByteBuff.getInt();
+ // 3 BODYCRC
+ messagesByteBuff.getInt();
+ // 4 FLAG
+ int flag = messagesByteBuff.getInt();
+ // 5 BODY
+ int bodyLen = messagesByteBuff.getInt();
+ int bodyPos = messagesByteBuff.position();
+ int bodyCrc = UtilAll.crc32(messagesByteBuff.array(), bodyPos, bodyLen);
+ messagesByteBuff.position(bodyPos + bodyLen);
+ // 6 properties
+ short propertiesLen = messagesByteBuff.getShort();
+ int propertiesPos = messagesByteBuff.position();
+ messagesByteBuff.position(propertiesPos + propertiesLen);
+
+ final byte[] topicData = messageExtBatch.getTopic().getBytes(MessageDecoder.CHARSET_UTF8);
+
+ final int topicLength = topicData.length;
+
+ final int msgLen = calMsgLength(messageExtBatch.getSysFlag(), bodyLen, topicLength, propertiesLen);
+ ByteBuffer msgStoreItemMemory = ByteBuffer.allocate(msgLen);
+
+ // Exceeds the maximum message
+ if (msgLen > this.maxMessageSize) {
+ CommitLog.log.warn("message size exceeded, msg total size: " + msgLen + ", msg body size: " +
+ bodyLen
+ + ", maxMessageSize: " + this.maxMessageSize);
+ throw new RuntimeException("message size exceeded");
+ }
+
+ totalMsgLen += msgLen;
+ // Determines whether there is sufficient free space
+ if (totalMsgLen > maxMessageSize) {
+ throw new RuntimeException("message size exceeded");
+ }
+
+ // Initialization of storage space
+ this.resetByteBuffer(msgStoreItemMemory, msgLen);
+ // 1 TOTALSIZE
+ msgStoreItemMemory.putInt(msgLen);
+ // 2 MAGICCODE
+ msgStoreItemMemory.putInt(DLedgerCommitLog.MESSAGE_MAGIC_CODE);
+ // 3 BODYCRC
+ msgStoreItemMemory.putInt(bodyCrc);
+ // 4 QUEUEID
+ msgStoreItemMemory.putInt(messageExtBatch.getQueueId());
+ // 5 FLAG
+ msgStoreItemMemory.putInt(flag);
+ // 6 QUEUEOFFSET
+ msgStoreItemMemory.putLong(0L);
+ // 7 PHYSICALOFFSET
+ msgStoreItemMemory.putLong(0);
+ // 8 SYSFLAG
+ msgStoreItemMemory.putInt(messageExtBatch.getSysFlag());
+ // 9 BORNTIMESTAMP
+ msgStoreItemMemory.putLong(messageExtBatch.getBornTimestamp());
+ // 10 BORNHOST
+ resetByteBuffer(bornHostHolder, bornHostLength);
+ msgStoreItemMemory.put(messageExtBatch.getBornHostBytes(bornHostHolder));
+ // 11 STORETIMESTAMP
+ msgStoreItemMemory.putLong(messageExtBatch.getStoreTimestamp());
+ // 12 STOREHOSTADDRESS
+ resetByteBuffer(storeHostHolder, storeHostLength);
+ msgStoreItemMemory.put(messageExtBatch.getStoreHostBytes(storeHostHolder));
+ // 13 RECONSUMETIMES
+ msgStoreItemMemory.putInt(messageExtBatch.getReconsumeTimes());
+ // 14 Prepared Transaction Offset
+ msgStoreItemMemory.putLong(0);
+ // 15 BODY
+ msgStoreItemMemory.putInt(bodyLen);
+ if (bodyLen > 0) {
+ msgStoreItemMemory.put(messagesByteBuff.array(), bodyPos, bodyLen);
+ }
+ // 16 TOPIC
+ msgStoreItemMemory.put((byte) topicLength);
+ msgStoreItemMemory.put(topicData);
+ // 17 PROPERTIES
+ msgStoreItemMemory.putShort(propertiesLen);
+ if (propertiesLen > 0) {
+ msgStoreItemMemory.put(messagesByteBuff.array(), propertiesPos, propertiesLen);
+ }
+ byte[] data = new byte[msgLen];
+ msgStoreItemMemory.clear();
+ msgStoreItemMemory.get(data);
+ batchBody.add(data);
+ }
+
+ return new EncodeResult(AppendMessageStatus.PUT_OK, key, batchBody, totalMsgLen);
}
private void resetByteBuffer(final ByteBuffer byteBuffer, final int limit) {
byteBuffer.flip();
byteBuffer.limit(limit);
}
-
}
public static class DLedgerSelectMappedBufferResult extends SelectMappedBufferResult {
@@ -740,6 +1209,7 @@ public class DLedgerCommitLog extends CommitLog {
this.sbr = sbr;
}
+ @Override
public synchronized void release() {
super.release();
if (sbr != null) {
diff --git a/store/src/main/java/org/apache/rocketmq/store/ha/HAService.java b/store/src/main/java/org/apache/rocketmq/store/ha/HAService.java
index a0e77fa3dc..34c51eb9e2 100644
--- a/store/src/main/java/org/apache/rocketmq/store/ha/HAService.java
+++ b/store/src/main/java/org/apache/rocketmq/store/ha/HAService.java
@@ -590,6 +590,13 @@ public class HAService {
log.info(this.getServiceName() + " service end");
}
+
+ @Override
+ public void shutdown() {
+ super.shutdown();
+ closeMaster();
+ }
+
// private void disableWriteFlag() {
// if (this.socketChannel != null) {
// SelectionKey sk = this.socketChannel.keyFor(this.selector);
diff --git a/store/src/test/java/org/apache/rocketmq/store/BatchPutMessageTest.java b/store/src/test/java/org/apache/rocketmq/store/BatchPutMessageTest.java
index 8618dbb0e5..b3a7c196f9 100644
--- a/store/src/test/java/org/apache/rocketmq/store/BatchPutMessageTest.java
+++ b/store/src/test/java/org/apache/rocketmq/store/BatchPutMessageTest.java
@@ -35,6 +35,7 @@ import java.io.File;
import java.net.InetSocketAddress;
import java.nio.charset.Charset;
import java.util.ArrayList;
+import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -80,6 +81,12 @@ public class BatchPutMessageTest {
@Test
public void testPutMessages() throws Exception {
+ String batchPropK = "extraKey";
+ String batchPropV = "extraValue";
+ Map batchProp = new HashMap<>(1);
+ batchProp.put(batchPropK, batchPropV);
+ short batchPropLen = (short) messageProperties2String(batchProp).getBytes(MessageDecoder.CHARSET_UTF8).length;
+
List messages = new ArrayList<>();
String topic = "batch-write-topic";
int queue = 0;
@@ -98,7 +105,7 @@ public class BatchPutMessageTest {
short propertiesLength = (short) propertiesBytes.length;
final byte[] topicData = msg.getTopic().getBytes(MessageDecoder.CHARSET_UTF8);
final int topicLength = topicData.length;
- msgLengthArr[j] = calMsgLength(msg.getBody().length, topicLength, propertiesLength) + msgLengthArr[j - 1];
+ msgLengthArr[j] = calMsgLength(msg.getBody().length, topicLength, propertiesLength+batchPropLen) + msgLengthArr[j - 1];
j++;
}
byte[] batchMessageBody = MessageDecoder.encodeMessages(messages);
@@ -106,6 +113,7 @@ public class BatchPutMessageTest {
messageExtBatch.setTopic(topic);
messageExtBatch.setQueueId(queue);
messageExtBatch.setBody(batchMessageBody);
+ messageExtBatch.putUserProperty(batchPropK,batchPropV);
messageExtBatch.setBornTimestamp(System.currentTimeMillis());
messageExtBatch.setStoreHost(new InetSocketAddress("127.0.0.1", 125));
messageExtBatch.setBornHost(new InetSocketAddress("127.0.0.1", 126));
diff --git a/store/src/test/java/org/apache/rocketmq/store/DefaultMessageStoreShutDownTest.java b/store/src/test/java/org/apache/rocketmq/store/DefaultMessageStoreShutDownTest.java
index e43bb4bc3d..db7d367e02 100644
--- a/store/src/test/java/org/apache/rocketmq/store/DefaultMessageStoreShutDownTest.java
+++ b/store/src/test/java/org/apache/rocketmq/store/DefaultMessageStoreShutDownTest.java
@@ -40,10 +40,11 @@ public class DefaultMessageStoreShutDownTest {
@Before
public void init() throws Exception {
- messageStore = spy(buildMessageStore());
- boolean load = messageStore.load();
+ DefaultMessageStore store = buildMessageStore();
+ boolean load = store.load();
assertTrue(load);
- messageStore.start();
+ store.start();
+ messageStore = spy(store);
when(messageStore.dispatchBehindBytes()).thenReturn(100L);
}
diff --git a/store/src/test/java/org/apache/rocketmq/store/DefaultMessageStoreTest.java b/store/src/test/java/org/apache/rocketmq/store/DefaultMessageStoreTest.java
index fd13e71a42..440f914631 100644
--- a/store/src/test/java/org/apache/rocketmq/store/DefaultMessageStoreTest.java
+++ b/store/src/test/java/org/apache/rocketmq/store/DefaultMessageStoreTest.java
@@ -133,7 +133,7 @@ public class DefaultMessageStoreTest {
StoreTestUtil.waitCommitLogReput((DefaultMessageStore) messageStore);
for (long i = 0; i < totalMsgs; i++) {
- GetMessageResult result = messageStore.getMessage("GROUP_A", "TOPIC_A", 0, i, 1024 * 1024, null);
+ GetMessageResult result = messageStore.getMessage("GROUP_A", "FooBar", 0, i, 1024 * 1024, null);
assertThat(result).isNotNull();
result.release();
}
@@ -471,7 +471,7 @@ public class DefaultMessageStoreTest {
StoreTestUtil.waitCommitLogReput((DefaultMessageStore) messageStore);
for (long i = 0; i < totalMsgs; i++) {
- GetMessageResult result = master.getMessage("GROUP_A", "TOPIC_A", 0, i, 1024 * 1024, null);
+ GetMessageResult result = master.getMessage("GROUP_A", "FooBar", 0, i, 1024 * 1024, null);
assertThat(result).isNotNull();
result.release();
diff --git a/store/src/test/java/org/apache/rocketmq/store/StoreTestBase.java b/store/src/test/java/org/apache/rocketmq/store/StoreTestBase.java
index a736754de4..5660de1363 100644
--- a/store/src/test/java/org/apache/rocketmq/store/StoreTestBase.java
+++ b/store/src/test/java/org/apache/rocketmq/store/StoreTestBase.java
@@ -16,17 +16,19 @@
*/
package org.apache.rocketmq.store;
+import org.apache.rocketmq.common.UtilAll;
+import org.apache.rocketmq.common.message.Message;
+import org.apache.rocketmq.common.message.MessageDecoder;
+import org.apache.rocketmq.common.message.MessageExtBatch;
+import org.junit.After;
+
import java.io.File;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.net.UnknownHostException;
-import java.util.HashSet;
-import java.util.Set;
-import java.util.UUID;
+import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
-import org.apache.rocketmq.common.UtilAll;
-import org.junit.After;
public class StoreTestBase {
@@ -44,6 +46,28 @@ public class StoreTestBase {
return port.addAndGet(5);
}
+ protected MessageExtBatch buildBatchMessage(int size) {
+ MessageExtBatch messageExtBatch = new MessageExtBatch();
+ messageExtBatch.setTopic("StoreTest");
+ messageExtBatch.setTags("TAG1");
+ messageExtBatch.setKeys("Hello");
+ messageExtBatch.setQueueId(Math.abs(QueueId.getAndIncrement()) % QUEUE_TOTAL);
+ messageExtBatch.setSysFlag(0);
+
+ messageExtBatch.setBornTimestamp(System.currentTimeMillis());
+ messageExtBatch.setBornHost(BornHost);
+ messageExtBatch.setStoreHost(StoreHost);
+
+ List messageList = new ArrayList<>(size);
+ for (int i = 0; i < size; i++) {
+ messageList.add(buildMessage());
+ }
+
+ messageExtBatch.setBody(MessageDecoder.encodeMessages(messageList));
+
+ return messageExtBatch;
+ }
+
protected MessageExtBrokerInner buildMessage() {
MessageExtBrokerInner msg = new MessageExtBrokerInner();
msg.setTopic("StoreTest");
@@ -59,6 +83,40 @@ public class StoreTestBase {
return msg;
}
+ protected MessageExtBatch buildIPv6HostBatchMessage(int size) {
+ MessageExtBatch messageExtBatch = new MessageExtBatch();
+ messageExtBatch.setTopic("StoreTest");
+ messageExtBatch.setTags("TAG1");
+ messageExtBatch.setKeys("Hello");
+ messageExtBatch.setBody(MessageBody);
+ messageExtBatch.setMsgId("24084004018081003FAA1DDE2B3F898A00002A9F0000000000000CA0");
+ messageExtBatch.setKeys(String.valueOf(System.currentTimeMillis()));
+ messageExtBatch.setQueueId(Math.abs(QueueId.getAndIncrement()) % QUEUE_TOTAL);
+ messageExtBatch.setSysFlag(0);
+ messageExtBatch.setBornHostV6Flag();
+ messageExtBatch.setStoreHostAddressV6Flag();
+ messageExtBatch.setBornTimestamp(System.currentTimeMillis());
+ try {
+ messageExtBatch.setBornHost(new InetSocketAddress(InetAddress.getByName("1050:0000:0000:0000:0005:0600:300c:326b"), 8123));
+ } catch (UnknownHostException e) {
+ e.printStackTrace();
+ }
+
+ try {
+ messageExtBatch.setStoreHost(new InetSocketAddress(InetAddress.getByName("::1"), 8123));
+ } catch (UnknownHostException e) {
+ e.printStackTrace();
+ }
+
+ List messageList = new ArrayList<>(size);
+ for (int i = 0; i < size; i++) {
+ messageList.add(buildIPv6HostMessage());
+ }
+
+ messageExtBatch.setBody(MessageDecoder.encodeMessages(messageList));
+ return messageExtBatch;
+ }
+
protected MessageExtBrokerInner buildIPv6HostMessage() {
MessageExtBrokerInner msg = new MessageExtBrokerInner();
msg.setTopic("StoreTest");
diff --git a/store/src/test/java/org/apache/rocketmq/store/dledger/DLedgerCommitlogTest.java b/store/src/test/java/org/apache/rocketmq/store/dledger/DLedgerCommitlogTest.java
index f0b9205302..8ab8a23b47 100644
--- a/store/src/test/java/org/apache/rocketmq/store/dledger/DLedgerCommitlogTest.java
+++ b/store/src/test/java/org/apache/rocketmq/store/dledger/DLedgerCommitlogTest.java
@@ -19,12 +19,17 @@ package org.apache.rocketmq.store.dledger;
import io.openmessaging.storage.dledger.DLedgerServer;
import io.openmessaging.storage.dledger.store.file.DLedgerMmapFileStore;
import io.openmessaging.storage.dledger.store.file.MmapFileList;
+
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.TimeUnit;
+
import org.apache.rocketmq.common.message.MessageDecoder;
import org.apache.rocketmq.common.message.MessageExt;
+import org.apache.rocketmq.common.message.MessageExtBatch;
import org.apache.rocketmq.store.DefaultMessageStore;
import org.apache.rocketmq.store.GetMessageResult;
import org.apache.rocketmq.store.GetMessageStatus;
@@ -39,7 +44,7 @@ public class DLedgerCommitlogTest extends MessageStoreTestBase {
@Test
public void testTruncateCQ() throws Exception {
- String base = createBaseDir();
+ String base = createBaseDir();
String peers = String.format("n0-localhost:%d", nextPort());
String group = UUID.randomUUID().toString();
String topic = UUID.randomUUID().toString();
@@ -92,10 +97,9 @@ public class DLedgerCommitlogTest extends MessageStoreTestBase {
}
-
@Test
public void testRecover() throws Exception {
- String base = createBaseDir();
+ String base = createBaseDir();
String peers = String.format("n0-localhost:%d", nextPort());
String group = UUID.randomUUID().toString();
String topic = UUID.randomUUID().toString();
@@ -133,10 +137,9 @@ public class DLedgerCommitlogTest extends MessageStoreTestBase {
}
-
@Test
public void testPutAndGetMessage() throws Exception {
- String base = createBaseDir();
+ String base = createBaseDir();
String peers = String.format("n0-localhost:%d", nextPort());
String group = UUID.randomUUID().toString();
DefaultMessageStore messageStore = createDledgerMessageStore(base, group, "n0", peers, null, false, 0);
@@ -146,7 +149,7 @@ public class DLedgerCommitlogTest extends MessageStoreTestBase {
List results = new ArrayList<>();
for (int i = 0; i < 10; i++) {
MessageExtBrokerInner msgInner =
- i < 5 ? buildMessage() : buildIPv6HostMessage();
+ i < 5 ? buildMessage() : buildIPv6HostMessage();
msgInner.setTopic(topic);
msgInner.setQueueId(0);
PutMessageResult putMessageResult = messageStore.putMessage(msgInner);
@@ -158,7 +161,7 @@ public class DLedgerCommitlogTest extends MessageStoreTestBase {
Assert.assertEquals(0, messageStore.getMinOffsetInQueue(topic, 0));
Assert.assertEquals(10, messageStore.getMaxOffsetInQueue(topic, 0));
Assert.assertEquals(0, messageStore.dispatchBehindBytes());
- GetMessageResult getMessageResult = messageStore.getMessage("group", topic, 0, 0, 32, null);
+ GetMessageResult getMessageResult = messageStore.getMessage("group", topic, 0, 0, 32, null);
Assert.assertEquals(GetMessageStatus.FOUND, getMessageResult.getStatus());
Assert.assertEquals(10, getMessageResult.getMessageBufferList().size());
@@ -175,15 +178,146 @@ public class DLedgerCommitlogTest extends MessageStoreTestBase {
messageStore.shutdown();
}
+ @Test
+ public void testBatchPutAndGetMessage() throws Exception {
+ String base = createBaseDir();
+ String peers = String.format("n0-localhost:%d", nextPort());
+ String group = UUID.randomUUID().toString();
+ DefaultMessageStore messageStore = createDledgerMessageStore(base, group, "n0", peers, null, false, 0);
+ Thread.sleep(1000);
+ String topic = UUID.randomUUID().toString();
+ // should be less than 4
+ int batchMessageSize = 2;
+ int repeat = 10;
+ List results = new ArrayList<>();
+ for (int i = 0; i < repeat; i++) {
+ MessageExtBatch messageExtBatch =
+ i < repeat / 10 ? buildBatchMessage(batchMessageSize) : buildIPv6HostBatchMessage(batchMessageSize);
+ messageExtBatch.setTopic(topic);
+ messageExtBatch.setQueueId(0);
+ PutMessageResult putMessageResult = messageStore.putMessages(messageExtBatch);
+ results.add(putMessageResult);
+ Assert.assertEquals(PutMessageStatus.PUT_OK, putMessageResult.getPutMessageStatus());
+ Assert.assertEquals(i * batchMessageSize, putMessageResult.getAppendMessageResult().getLogicsOffset());
+ }
+ Thread.sleep(100);
+ Assert.assertEquals(0, messageStore.getMinOffsetInQueue(topic, 0));
+ Assert.assertEquals(repeat * batchMessageSize, messageStore.getMaxOffsetInQueue(topic, 0));
+ Assert.assertEquals(0, messageStore.dispatchBehindBytes());
+ GetMessageResult getMessageResult = messageStore.getMessage("group", topic, 0, 0, 100, null);
+ Assert.assertEquals(GetMessageStatus.FOUND, getMessageResult.getStatus());
+
+ Assert.assertEquals(repeat * batchMessageSize > 32 ? 32 : repeat * batchMessageSize, getMessageResult.getMessageBufferList().size());
+ Assert.assertEquals(repeat * batchMessageSize > 32 ? 32 : repeat * batchMessageSize, getMessageResult.getMessageMapedList().size());
+ Assert.assertEquals(repeat * batchMessageSize, getMessageResult.getMaxOffset());
+
+ for (int i = 0; i < results.size(); i++) {
+ ByteBuffer buffer = getMessageResult.getMessageBufferList().get(i * batchMessageSize);
+ MessageExt messageExt = MessageDecoder.decode(buffer);
+ Assert.assertEquals(i * batchMessageSize, messageExt.getQueueOffset());
+ Assert.assertEquals(results.get(i).getAppendMessageResult().getMsgId().split(",").length, batchMessageSize);
+ Assert.assertEquals(results.get(i).getAppendMessageResult().getWroteOffset(), messageExt.getCommitLogOffset());
+ }
+ messageStore.destroy();
+ messageStore.shutdown();
+ }
+
+ @Test
+ public void testAsyncPutAndGetMessage() throws Exception {
+ String base = createBaseDir();
+ String peers = String.format("n0-localhost:%d", nextPort());
+ String group = UUID.randomUUID().toString();
+ DefaultMessageStore messageStore = createDledgerMessageStore(base, group, "n0", peers, null, false, 0);
+ Thread.sleep(1000);
+ String topic = UUID.randomUUID().toString();
+
+ List results = new ArrayList<>();
+ for (int i = 0; i < 10; i++) {
+ MessageExtBrokerInner msgInner =
+ i < 5 ? buildMessage() : buildIPv6HostMessage();
+ msgInner.setTopic(topic);
+ msgInner.setQueueId(0);
+ CompletableFuture futureResult = messageStore.asyncPutMessage(msgInner);
+ PutMessageResult putMessageResult = futureResult.get(3000, TimeUnit.MILLISECONDS);
+ results.add(putMessageResult);
+ Assert.assertEquals(PutMessageStatus.PUT_OK, putMessageResult.getPutMessageStatus());
+ Assert.assertEquals(i, putMessageResult.getAppendMessageResult().getLogicsOffset());
+ }
+ Thread.sleep(100);
+ Assert.assertEquals(0, messageStore.getMinOffsetInQueue(topic, 0));
+ Assert.assertEquals(10, messageStore.getMaxOffsetInQueue(topic, 0));
+ Assert.assertEquals(0, messageStore.dispatchBehindBytes());
+ GetMessageResult getMessageResult = messageStore.getMessage("group", topic, 0, 0, 32, null);
+ Assert.assertEquals(GetMessageStatus.FOUND, getMessageResult.getStatus());
+
+ Assert.assertEquals(10, getMessageResult.getMessageBufferList().size());
+ Assert.assertEquals(10, getMessageResult.getMessageMapedList().size());
+
+ for (int i = 0; i < results.size(); i++) {
+ ByteBuffer buffer = getMessageResult.getMessageBufferList().get(i);
+ MessageExt messageExt = MessageDecoder.decode(buffer);
+ Assert.assertEquals(i, messageExt.getQueueOffset());
+ Assert.assertEquals(results.get(i).getAppendMessageResult().getMsgId(), messageExt.getMsgId());
+ Assert.assertEquals(results.get(i).getAppendMessageResult().getWroteOffset(), messageExt.getCommitLogOffset());
+ }
+ messageStore.destroy();
+ messageStore.shutdown();
+ }
+
+ @Test
+ public void testAsyncBatchPutAndGetMessage() throws Exception {
+ String base = createBaseDir();
+ String peers = String.format("n0-localhost:%d", nextPort());
+ String group = UUID.randomUUID().toString();
+ DefaultMessageStore messageStore = createDledgerMessageStore(base, group, "n0", peers, null, false, 0);
+ Thread.sleep(1000);
+ String topic = UUID.randomUUID().toString();
+ // should be less than 4
+ int batchMessageSize = 2;
+ int repeat = 10;
+
+ List results = new ArrayList<>();
+ for (int i = 0; i < repeat; i++) {
+ MessageExtBatch messageExtBatch =
+ i < 5 ? buildBatchMessage(batchMessageSize) : buildIPv6HostBatchMessage(batchMessageSize);
+ messageExtBatch.setTopic(topic);
+ messageExtBatch.setQueueId(0);
+ CompletableFuture futureResult = messageStore.asyncPutMessages(messageExtBatch);
+ PutMessageResult putMessageResult = futureResult.get(3000, TimeUnit.MILLISECONDS);
+ results.add(putMessageResult);
+ Assert.assertEquals(PutMessageStatus.PUT_OK, putMessageResult.getPutMessageStatus());
+ Assert.assertEquals(i * batchMessageSize, putMessageResult.getAppendMessageResult().getLogicsOffset());
+ }
+ Thread.sleep(100);
+ Assert.assertEquals(0, messageStore.getMinOffsetInQueue(topic, 0));
+ Assert.assertEquals(repeat * batchMessageSize, messageStore.getMaxOffsetInQueue(topic, 0));
+ Assert.assertEquals(0, messageStore.dispatchBehindBytes());
+ GetMessageResult getMessageResult = messageStore.getMessage("group", topic, 0, 0, 32, null);
+ Assert.assertEquals(GetMessageStatus.FOUND, getMessageResult.getStatus());
+
+ Assert.assertEquals(repeat * batchMessageSize > 32 ? 32 : repeat * batchMessageSize, getMessageResult.getMessageBufferList().size());
+ Assert.assertEquals(repeat * batchMessageSize > 32 ? 32 : repeat * batchMessageSize, getMessageResult.getMessageMapedList().size());
+ Assert.assertEquals(repeat * batchMessageSize, getMessageResult.getMaxOffset());
+
+ for (int i = 0; i < results.size(); i++) {
+ ByteBuffer buffer = getMessageResult.getMessageBufferList().get(i * batchMessageSize);
+ MessageExt messageExt = MessageDecoder.decode(buffer);
+ Assert.assertEquals(i * batchMessageSize, messageExt.getQueueOffset());
+ Assert.assertEquals(results.get(i).getAppendMessageResult().getMsgId().split(",").length, batchMessageSize);
+ Assert.assertEquals(results.get(i).getAppendMessageResult().getWroteOffset(), messageExt.getCommitLogOffset());
+ }
+ messageStore.destroy();
+ messageStore.shutdown();
+ }
@Test
public void testCommittedPos() throws Exception {
String peers = String.format("n0-localhost:%d;n1-localhost:%d", nextPort(), nextPort());
String group = UUID.randomUUID().toString();
- DefaultMessageStore leaderStore = createDledgerMessageStore(createBaseDir(), group,"n0", peers, "n0", false, 0);
+ DefaultMessageStore leaderStore = createDledgerMessageStore(createBaseDir(), group, "n0", peers, "n0", false, 0);
String topic = UUID.randomUUID().toString();
- MessageExtBrokerInner msgInner = buildMessage();
+ MessageExtBrokerInner msgInner = buildMessage();
msgInner.setTopic(topic);
msgInner.setQueueId(0);
PutMessageResult putMessageResult = leaderStore.putMessage(msgInner);
@@ -195,7 +329,7 @@ public class DLedgerCommitlogTest extends MessageStoreTestBase {
Assert.assertEquals(0, leaderStore.getMaxOffsetInQueue(topic, 0));
- DefaultMessageStore followerStore = createDledgerMessageStore(createBaseDir(), group,"n1", peers, "n0", false, 0);
+ DefaultMessageStore followerStore = createDledgerMessageStore(createBaseDir(), group, "n1", peers, "n0", false, 0);
Thread.sleep(2000);
Assert.assertEquals(1, leaderStore.getMaxOffsetInQueue(topic, 0));
@@ -214,10 +348,10 @@ public class DLedgerCommitlogTest extends MessageStoreTestBase {
public void testIPv6HostMsgCommittedPos() throws Exception {
String peers = String.format("n0-localhost:%d;n1-localhost:%d", nextPort(), nextPort());
String group = UUID.randomUUID().toString();
- DefaultMessageStore leaderStore = createDledgerMessageStore(createBaseDir(), group,"n0", peers, "n0", false, 0);
+ DefaultMessageStore leaderStore = createDledgerMessageStore(createBaseDir(), group, "n0", peers, "n0", false, 0);
String topic = UUID.randomUUID().toString();
- MessageExtBrokerInner msgInner = buildIPv6HostMessage();
+ MessageExtBrokerInner msgInner = buildIPv6HostMessage();
msgInner.setTopic(topic);
msgInner.setQueueId(0);
PutMessageResult putMessageResult = leaderStore.putMessage(msgInner);
@@ -229,7 +363,7 @@ public class DLedgerCommitlogTest extends MessageStoreTestBase {
Assert.assertEquals(0, leaderStore.getMaxOffsetInQueue(topic, 0));
- DefaultMessageStore followerStore = createDledgerMessageStore(createBaseDir(), group,"n1", peers, "n0", false, 0);
+ DefaultMessageStore followerStore = createDledgerMessageStore(createBaseDir(), group, "n1", peers, "n0", false, 0);
Thread.sleep(2000);
Assert.assertEquals(1, leaderStore.getMaxOffsetInQueue(topic, 0));
diff --git a/test/pom.xml b/test/pom.xml
index 8fc5a71218..851d9ab9aa 100644
--- a/test/pom.xml
+++ b/test/pom.xml
@@ -20,7 +20,7 @@
rocketmq-all
org.apache.rocketmq
- 4.8.0-SNAPSHOT
+ 4.8.1-SNAPSHOT
4.0.0
diff --git a/test/src/main/java/org/apache/rocketmq/test/util/FileUtil.java b/test/src/main/java/org/apache/rocketmq/test/util/FileUtil.java
index 44db782b5c..e08967eb91 100644
--- a/test/src/main/java/org/apache/rocketmq/test/util/FileUtil.java
+++ b/test/src/main/java/org/apache/rocketmq/test/util/FileUtil.java
@@ -33,7 +33,7 @@ public class FileUtil {
this.fileName = fileName;
}
- public static void main(String args[]) {
+ public static void main(String[] args) {
String filePath = FileUtil.class.getResource("/").getPath();
String fileName = "test.txt";
FileUtil fileUtil = new FileUtil(filePath, fileName);
diff --git a/test/src/main/java/org/apache/rocketmq/test/util/MQWait.java b/test/src/main/java/org/apache/rocketmq/test/util/MQWait.java
index 6edeecadb2..0c24427d92 100644
--- a/test/src/main/java/org/apache/rocketmq/test/util/MQWait.java
+++ b/test/src/main/java/org/apache/rocketmq/test/util/MQWait.java
@@ -76,7 +76,7 @@ public class MQWait {
}
}
- public static void main(String args[]) {
+ public static void main(String[] args) {
long start = System.currentTimeMillis();
MQWait.setCondition(new Condition() {
diff --git a/test/src/main/java/org/apache/rocketmq/test/util/RandomUtil.java b/test/src/main/java/org/apache/rocketmq/test/util/RandomUtil.java
index 1c2bdac305..41cacb684c 100644
--- a/test/src/main/java/org/apache/rocketmq/test/util/RandomUtil.java
+++ b/test/src/main/java/org/apache/rocketmq/test/util/RandomUtil.java
@@ -100,14 +100,14 @@ public final class RandomUtil {
return n + res % (m - n);
}
- private static char getChar(int arg[]) {
+ private static char getChar(int[] arg) {
int size = arg.length;
int c = rd.nextInt(size / 2);
c = c * 2;
return (char) (getIntegerBetween(arg[c], arg[c + 1]));
}
- private static String getString(int n, int arg[]) {
+ private static String getString(int n, int[] arg) {
StringBuilder res = new StringBuilder();
for (int i = 0; i < n; i++) {
res.append(getChar(arg));
@@ -116,17 +116,17 @@ public final class RandomUtil {
}
public static String getStringWithCharacter(int n) {
- int arg[] = new int[] {'a', 'z' + 1, 'A', 'Z' + 1};
+ int[] arg = new int[] {'a', 'z' + 1, 'A', 'Z' + 1};
return getString(n, arg);
}
public static String getStringWithNumber(int n) {
- int arg[] = new int[] {'0', '9' + 1};
+ int[] arg = new int[] {'0', '9' + 1};
return getString(n, arg);
}
public static String getStringWithNumAndCha(int n) {
- int arg[] = new int[] {'a', 'z' + 1, 'A', 'Z' + 1, '0', '9' + 1};
+ int[] arg = new int[] {'a', 'z' + 1, 'A', 'Z' + 1, '0', '9' + 1};
return getString(n, arg);
}
diff --git a/test/src/main/java/org/apache/rocketmq/test/util/RandomUtils.java b/test/src/main/java/org/apache/rocketmq/test/util/RandomUtils.java
index 9eca28bbe7..3f71176d6f 100644
--- a/test/src/main/java/org/apache/rocketmq/test/util/RandomUtils.java
+++ b/test/src/main/java/org/apache/rocketmq/test/util/RandomUtils.java
@@ -45,16 +45,16 @@ public class RandomUtils {
}
public static String getStringWithNumber(int n) {
- int arg[] = new int[] {'0', '9' + 1};
+ int[] arg = new int[] {'0', '9' + 1};
return getString(n, arg);
}
public static String getStringWithCharacter(int n) {
- int arg[] = new int[] {'a', 'z' + 1, 'A', 'Z' + 1};
+ int[] arg = new int[] {'a', 'z' + 1, 'A', 'Z' + 1};
return getString(n, arg);
}
- private static String getString(int n, int arg[]) {
+ private static String getString(int n, int[] arg) {
StringBuilder res = new StringBuilder();
for (int i = 0; i < n; i++) {
res.append(getChar(arg));
@@ -62,7 +62,7 @@ public class RandomUtils {
return res.toString();
}
- private static char getChar(int arg[]) {
+ private static char getChar(int[] arg) {
int size = arg.length;
int c = rd.nextInt(size / 2);
c = c * 2;
diff --git a/test/src/main/java/org/apache/rocketmq/test/util/VerifyUtils.java b/test/src/main/java/org/apache/rocketmq/test/util/VerifyUtils.java
index 965d2ee670..69bfd8f7d1 100644
--- a/test/src/main/java/org/apache/rocketmq/test/util/VerifyUtils.java
+++ b/test/src/main/java/org/apache/rocketmq/test/util/VerifyUtils.java
@@ -140,7 +140,7 @@ public class VerifyUtils {
return rtExpect;
}
- public static void main(String args[]) {
+ public static void main(String[] args) {
verifyBalance(400, 0.1f, 230, 190);
}
}
diff --git a/test/src/main/java/org/apache/rocketmq/test/util/data/collect/impl/ListDataCollectorImpl.java b/test/src/main/java/org/apache/rocketmq/test/util/data/collect/impl/ListDataCollectorImpl.java
index 82ab461aa5..bdd991a335 100644
--- a/test/src/main/java/org/apache/rocketmq/test/util/data/collect/impl/ListDataCollectorImpl.java
+++ b/test/src/main/java/org/apache/rocketmq/test/util/data/collect/impl/ListDataCollectorImpl.java
@@ -43,7 +43,7 @@ public class ListDataCollectorImpl implements DataCollector {
return datas;
}
- public void resetData() {
+ public synchronized void resetData() {
datas.clear();
unlockIncrement();
}
@@ -67,7 +67,7 @@ public class ListDataCollectorImpl implements DataCollector {
return Collections.frequency(datas, data) == 1;
}
- public Collection getAllDataWithoutDuplicate() {
+ public synchronized Collection getAllDataWithoutDuplicate() {
return new HashSet(datas);
}
@@ -81,7 +81,7 @@ public class ListDataCollectorImpl implements DataCollector {
return res;
}
- public void removeData(Object data) {
+ public synchronized void removeData(Object data) {
datas.remove(data);
}
diff --git a/test/src/test/java/org/apache/rocketmq/test/client/consumer/tag/MulTagSubIT.java b/test/src/test/java/org/apache/rocketmq/test/client/consumer/tag/MulTagSubIT.java
index 564da5ceaf..0edbdbe2e3 100644
--- a/test/src/test/java/org/apache/rocketmq/test/client/consumer/tag/MulTagSubIT.java
+++ b/test/src/test/java/org/apache/rocketmq/test/client/consumer/tag/MulTagSubIT.java
@@ -92,7 +92,7 @@ public class MulTagSubIT extends BaseConf {
@Test
public void testSubTwoTabAndMatchTwo() {
- String tags[] = {"jueyin1", "jueyin2"};
+ String[] tags = {"jueyin1", "jueyin2"};
String subExpress = String.format("%s||%s", tags[0], tags[1]);
int msgSize = 10;
@@ -113,7 +113,7 @@ public class MulTagSubIT extends BaseConf {
@Test
public void testSubThreeTabAndMatchTwo() {
- String tags[] = {"jueyin1", "jueyin2", "jueyin3"};
+ String[] tags = {"jueyin1", "jueyin2", "jueyin3"};
String subExpress = String.format("%s||%s", tags[0], tags[1]);
int msgSize = 10;
@@ -135,7 +135,7 @@ public class MulTagSubIT extends BaseConf {
@Test
public void testNoMatch() {
- String tags[] = {"jueyin1", "jueyin2", "jueyin3"};
+ String[] tags = {"jueyin1", "jueyin2", "jueyin3"};
String subExpress = "no_match";
int msgSize = 10;
diff --git a/test/src/test/java/org/apache/rocketmq/test/client/consumer/tag/TagMessageWithMulConsumerIT.java b/test/src/test/java/org/apache/rocketmq/test/client/consumer/tag/TagMessageWithMulConsumerIT.java
index 31321975b5..8de1b7d4e0 100644
--- a/test/src/test/java/org/apache/rocketmq/test/client/consumer/tag/TagMessageWithMulConsumerIT.java
+++ b/test/src/test/java/org/apache/rocketmq/test/client/consumer/tag/TagMessageWithMulConsumerIT.java
@@ -84,7 +84,7 @@ public class TagMessageWithMulConsumerIT extends BaseConf {
@Test
public void testSendMessagesWithTwoTag() {
- String tags[] = {"jueyin1", "jueyin2"};
+ String[] tags = {"jueyin1", "jueyin2"};
int msgSize = 10;
TagMessage tagMessage = new TagMessage(tags, topic, msgSize);
@@ -113,7 +113,7 @@ public class TagMessageWithMulConsumerIT extends BaseConf {
@Test
public void testTwoConsumerOneMatchOneOtherMatchAll() {
- String tags[] = {"jueyin1", "jueyin2"};
+ String[] tags = {"jueyin1", "jueyin2"};
String sub1 = String.format("%s||%s", tags[0], tags[1]);
String sub2 = String.format("%s|| noExist", tags[0]);
int msgSize = 10;
@@ -144,7 +144,7 @@ public class TagMessageWithMulConsumerIT extends BaseConf {
@Test
public void testSubKindsOf() {
- String tags[] = {"jueyin1", "jueyin2"};
+ String[] tags = {"jueyin1", "jueyin2"};
String sub1 = String.format("%s||%s", tags[0], tags[1]);
String sub2 = String.format("%s|| noExist", tags[0]);
String sub3 = tags[0];
diff --git a/test/src/test/resources/log4j.xml b/test/src/test/resources/log4j.xml
index 3031095e70..7840ab78c1 100644
--- a/test/src/test/resources/log4j.xml
+++ b/test/src/test/resources/log4j.xml
@@ -30,7 +30,7 @@
-
+
diff --git a/tools/pom.xml b/tools/pom.xml
index 4c1b647577..eeccae81bf 100644
--- a/tools/pom.xml
+++ b/tools/pom.xml
@@ -19,7 +19,7 @@
org.apache.rocketmq
rocketmq-all
- 4.8.0-SNAPSHOT
+ 4.8.1-SNAPSHOT
4.0.0
diff --git a/tools/src/main/java/org/apache/rocketmq/tools/admin/DefaultMQAdminExt.java b/tools/src/main/java/org/apache/rocketmq/tools/admin/DefaultMQAdminExt.java
index e80a813eca..8b1c228f4f 100644
--- a/tools/src/main/java/org/apache/rocketmq/tools/admin/DefaultMQAdminExt.java
+++ b/tools/src/main/java/org/apache/rocketmq/tools/admin/DefaultMQAdminExt.java
@@ -320,6 +320,13 @@ public class DefaultMQAdminExt extends ClientConfig implements MQAdminExt {
defaultMQAdminExtImpl.deleteSubscriptionGroup(addr, groupName);
}
+ @Override
+ public void deleteSubscriptionGroup(String addr,
+ String groupName, boolean removeOffset) throws RemotingException, MQBrokerException, InterruptedException,
+ MQClientException {
+ defaultMQAdminExtImpl.deleteSubscriptionGroup(addr, groupName, removeOffset);
+ }
+
@Override
public void createAndUpdateKvConfig(String namespace, String key,
String value) throws RemotingException, MQBrokerException,
diff --git a/tools/src/main/java/org/apache/rocketmq/tools/admin/DefaultMQAdminExtImpl.java b/tools/src/main/java/org/apache/rocketmq/tools/admin/DefaultMQAdminExtImpl.java
index 22d4005ce9..5c343708b3 100644
--- a/tools/src/main/java/org/apache/rocketmq/tools/admin/DefaultMQAdminExtImpl.java
+++ b/tools/src/main/java/org/apache/rocketmq/tools/admin/DefaultMQAdminExtImpl.java
@@ -424,7 +424,14 @@ public class DefaultMQAdminExtImpl implements MQAdminExt, MQAdminExtInner {
public void deleteSubscriptionGroup(String addr,
String groupName) throws RemotingException, MQBrokerException, InterruptedException,
MQClientException {
- this.mqClientInstance.getMQClientAPIImpl().deleteSubscriptionGroup(addr, groupName, timeoutMillis);
+ this.mqClientInstance.getMQClientAPIImpl().deleteSubscriptionGroup(addr, groupName, false, timeoutMillis);
+ }
+
+ @Override
+ public void deleteSubscriptionGroup(String addr,
+ String groupName, boolean removeOffset) throws RemotingException, MQBrokerException, InterruptedException,
+ MQClientException {
+ this.mqClientInstance.getMQClientAPIImpl().deleteSubscriptionGroup(addr, groupName, removeOffset, timeoutMillis);
}
@Override
diff --git a/tools/src/main/java/org/apache/rocketmq/tools/admin/MQAdminExt.java b/tools/src/main/java/org/apache/rocketmq/tools/admin/MQAdminExt.java
index 17b62251c6..d5462cb04e 100644
--- a/tools/src/main/java/org/apache/rocketmq/tools/admin/MQAdminExt.java
+++ b/tools/src/main/java/org/apache/rocketmq/tools/admin/MQAdminExt.java
@@ -152,6 +152,9 @@ public interface MQAdminExt extends MQAdmin {
void deleteSubscriptionGroup(final String addr, String groupName) throws RemotingException, MQBrokerException,
InterruptedException, MQClientException;
+ void deleteSubscriptionGroup(final String addr, String groupName, boolean removeOffset) throws RemotingException, MQBrokerException,
+ InterruptedException, MQClientException;
+
void createAndUpdateKvConfig(String namespace, String key,
String value) throws RemotingException, MQBrokerException,
InterruptedException, MQClientException;
diff --git a/tools/src/main/java/org/apache/rocketmq/tools/command/cluster/CLusterSendMsgRTCommand.java b/tools/src/main/java/org/apache/rocketmq/tools/command/cluster/CLusterSendMsgRTCommand.java
index 5038123561..872a130d9f 100644
--- a/tools/src/main/java/org/apache/rocketmq/tools/command/cluster/CLusterSendMsgRTCommand.java
+++ b/tools/src/main/java/org/apache/rocketmq/tools/command/cluster/CLusterSendMsgRTCommand.java
@@ -38,7 +38,7 @@ import org.apache.rocketmq.tools.command.SubCommandException;
public class CLusterSendMsgRTCommand implements SubCommand {
- public static void main(String args[]) {
+ public static void main(String[] args) {
}
@Override
diff --git a/tools/src/main/java/org/apache/rocketmq/tools/command/consumer/ConsumerProgressSubCommand.java b/tools/src/main/java/org/apache/rocketmq/tools/command/consumer/ConsumerProgressSubCommand.java
index b946ee141e..7985f9d591 100644
--- a/tools/src/main/java/org/apache/rocketmq/tools/command/consumer/ConsumerProgressSubCommand.java
+++ b/tools/src/main/java/org/apache/rocketmq/tools/command/consumer/ConsumerProgressSubCommand.java
@@ -111,17 +111,26 @@ public class ConsumerProgressSubCommand implements SubCommand {
if (showClientIP) {
messageQueueAllocationResult = getMessageQueueAllocationResult(defaultMQAdminExt, consumerGroup);
}
-
- System.out.printf("%-32s %-32s %-4s %-20s %-20s %-20s %-20s %s%n",
- "#Topic",
- "#Broker Name",
- "#QID",
- "#Broker Offset",
- "#Consumer Offset",
- "#Client IP",
- "#Diff",
- "#LastTime");
-
+ if (showClientIP) {
+ System.out.printf("%-32s %-32s %-4s %-20s %-20s %-20s %-20s %s%n",
+ "#Topic",
+ "#Broker Name",
+ "#QID",
+ "#Broker Offset",
+ "#Consumer Offset",
+ "#Client IP",
+ "#Diff",
+ "#LastTime");
+ } else {
+ System.out.printf("%-32s %-32s %-4s %-20s %-20s %-20s %s%n",
+ "#Topic",
+ "#Broker Name",
+ "#QID",
+ "#Broker Offset",
+ "#Consumer Offset",
+ "#Diff",
+ "#LastTime");
+ }
long diffTotal = 0L;
for (MessageQueue mq : mqList) {
OffsetWrapper offsetWrapper = consumeStats.getOffsetTable().get(mq);
@@ -141,17 +150,28 @@ public class ConsumerProgressSubCommand implements SubCommand {
if (showClientIP) {
clientIP = messageQueueAllocationResult.get(mq);
}
-
- System.out.printf("%-32s %-32s %-4d %-20d %-20d %-20s %-20d %s%n",
- UtilAll.frontStringAtLeast(mq.getTopic(), 32),
- UtilAll.frontStringAtLeast(mq.getBrokerName(), 32),
- mq.getQueueId(),
- offsetWrapper.getBrokerOffset(),
- offsetWrapper.getConsumerOffset(),
- null != clientIP ? clientIP : "N/A",
- diff,
- lastTime
- );
+ if (showClientIP) {
+ System.out.printf("%-32s %-32s %-4d %-20d %-20d %-20s %-20d %s%n",
+ UtilAll.frontStringAtLeast(mq.getTopic(), 32),
+ UtilAll.frontStringAtLeast(mq.getBrokerName(), 32),
+ mq.getQueueId(),
+ offsetWrapper.getBrokerOffset(),
+ offsetWrapper.getConsumerOffset(),
+ null != clientIP ? clientIP : "N/A",
+ diff,
+ lastTime
+ );
+ } else {
+ System.out.printf("%-32s %-32s %-4d %-20d %-20d %-20d %s%n",
+ UtilAll.frontStringAtLeast(mq.getTopic(), 32),
+ UtilAll.frontStringAtLeast(mq.getBrokerName(), 32),
+ mq.getQueueId(),
+ offsetWrapper.getBrokerOffset(),
+ offsetWrapper.getConsumerOffset(),
+ diff,
+ lastTime
+ );
+ }
}
System.out.printf("%n");
diff --git a/tools/src/main/java/org/apache/rocketmq/tools/command/consumer/DeleteSubscriptionGroupCommand.java b/tools/src/main/java/org/apache/rocketmq/tools/command/consumer/DeleteSubscriptionGroupCommand.java
index 96d81956e4..fb0efebaa2 100644
--- a/tools/src/main/java/org/apache/rocketmq/tools/command/consumer/DeleteSubscriptionGroupCommand.java
+++ b/tools/src/main/java/org/apache/rocketmq/tools/command/consumer/DeleteSubscriptionGroupCommand.java
@@ -54,6 +54,10 @@ public class DeleteSubscriptionGroupCommand implements SubCommand {
opt.setRequired(true);
options.addOption(opt);
+ opt = new Option("r", "removeOffset", true, "remove offset");
+ opt.setRequired(false);
+ options.addOption(opt);
+
return options;
}
@@ -65,11 +69,16 @@ public class DeleteSubscriptionGroupCommand implements SubCommand {
// groupName
String groupName = commandLine.getOptionValue('g').trim();
+ boolean removeOffset = false;
+ if (commandLine.hasOption('r')) {
+ removeOffset = Boolean.valueOf(commandLine.getOptionValue("r").trim());
+ }
+
if (commandLine.hasOption('b')) {
String addr = commandLine.getOptionValue('b').trim();
adminExt.start();
- adminExt.deleteSubscriptionGroup(addr, groupName);
+ adminExt.deleteSubscriptionGroup(addr, groupName, removeOffset);
System.out.printf("delete subscription group [%s] from broker [%s] success.%n", groupName,
addr);
@@ -80,7 +89,7 @@ public class DeleteSubscriptionGroupCommand implements SubCommand {
Set masterSet = CommandUtil.fetchMasterAddrByClusterName(adminExt, clusterName);
for (String master : masterSet) {
- adminExt.deleteSubscriptionGroup(master, groupName);
+ adminExt.deleteSubscriptionGroup(master, groupName, removeOffset);
System.out.printf(
"delete subscription group [%s] from broker [%s] in cluster [%s] success.%n",
groupName, master, clusterName);
diff --git a/tools/src/main/java/org/apache/rocketmq/tools/command/topic/TopicRouteSubCommand.java b/tools/src/main/java/org/apache/rocketmq/tools/command/topic/TopicRouteSubCommand.java
index c770db01d4..a78a4a63ab 100644
--- a/tools/src/main/java/org/apache/rocketmq/tools/command/topic/TopicRouteSubCommand.java
+++ b/tools/src/main/java/org/apache/rocketmq/tools/command/topic/TopicRouteSubCommand.java
@@ -19,14 +19,23 @@ package org.apache.rocketmq.tools.command.topic;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.Option;
import org.apache.commons.cli.Options;
+import org.apache.rocketmq.common.protocol.route.BrokerData;
+import org.apache.rocketmq.common.protocol.route.QueueData;
import org.apache.rocketmq.common.protocol.route.TopicRouteData;
import org.apache.rocketmq.remoting.RPCHook;
import org.apache.rocketmq.tools.admin.DefaultMQAdminExt;
import org.apache.rocketmq.tools.command.SubCommand;
import org.apache.rocketmq.tools.command.SubCommandException;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
public class TopicRouteSubCommand implements SubCommand {
+ private static final String FORMAT = "%-45s %-32s %-50s %-10s %-11s %-5s%n";
+
@Override
public String commandName() {
return "topicRoute";
@@ -43,6 +52,9 @@ public class TopicRouteSubCommand implements SubCommand {
opt.setRequired(true);
options.addOption(opt);
+ opt = new Option("l", "list", false, "Use list format to print data");
+ opt.setRequired(false);
+ options.addOption(opt);
return options;
}
@@ -58,12 +70,46 @@ public class TopicRouteSubCommand implements SubCommand {
String topic = commandLine.getOptionValue('t').trim();
TopicRouteData topicRouteData = defaultMQAdminExt.examineTopicRouteInfo(topic);
- String json = topicRouteData.toJson(true);
- System.out.printf("%s%n", json);
+ printData(topicRouteData, commandLine.hasOption('l'));
} catch (Exception e) {
throw new SubCommandException(this.getClass().getSimpleName() + " command failed", e);
} finally {
defaultMQAdminExt.shutdown();
}
}
-}
+
+ private void printData(TopicRouteData topicRouteData, boolean useListFormat) {
+ if (!useListFormat) {
+ System.out.printf("%s%n", topicRouteData.toJson(true));
+ return;
+ }
+
+ int totalReadQueue = 0, totalWriteQueue = 0;
+ List queueDataList = topicRouteData.getQueueDatas();
+ Map map = new HashMap<>();
+ for (QueueData queueData : queueDataList) {
+ map.put(queueData.getBrokerName(), queueData);
+ }
+ queueDataList.sort(Comparator.comparing(QueueData::getBrokerName));
+
+ List brokerDataList = topicRouteData.getBrokerDatas();
+ brokerDataList.sort(Comparator.comparing(BrokerData::getBrokerName));
+
+ System.out.printf(FORMAT, "#ClusterName", "#BrokerName", "#BrokerAddrs", "#ReadQueue", "#WriteQueue", "#Perm");
+
+ for (BrokerData brokerData : brokerDataList) {
+ String brokerName = brokerData.getBrokerName();
+ QueueData queueData = map.get(brokerName);
+ totalReadQueue += queueData.getReadQueueNums();
+ totalWriteQueue += queueData.getWriteQueueNums();
+ System.out.printf(FORMAT, brokerData.getCluster(), brokerName, brokerData.getBrokerAddrs(),
+ queueData.getReadQueueNums(), queueData.getWriteQueueNums(), queueData.getPerm());
+ }
+
+ for (int i = 0; i < 158; i++) {
+ System.out.print("-");
+ }
+ System.out.printf("%n");
+ System.out.printf(FORMAT, "Total:", map.keySet().size(), "", totalReadQueue, totalWriteQueue, "");
+ }
+}
\ No newline at end of file
diff --git a/tools/src/main/java/org/apache/rocketmq/tools/command/topic/UpdateTopicPermSubCommand.java b/tools/src/main/java/org/apache/rocketmq/tools/command/topic/UpdateTopicPermSubCommand.java
index a06a19d1fd..63a2a19275 100644
--- a/tools/src/main/java/org/apache/rocketmq/tools/command/topic/UpdateTopicPermSubCommand.java
+++ b/tools/src/main/java/org/apache/rocketmq/tools/command/topic/UpdateTopicPermSubCommand.java
@@ -94,7 +94,7 @@ public class UpdateTopicPermSubCommand implements SubCommand {
topicConfig.setTopicName(topic);
topicConfig.setWriteQueueNums(queueData.getWriteQueueNums());
topicConfig.setReadQueueNums(queueData.getReadQueueNums());
- topicConfig.setTopicSysFlag(queueData.getTopicSynFlag());
+ topicConfig.setTopicSysFlag(queueData.getTopicSysFlag());
//new perm
int perm;
if (commandLine.hasOption('p')) {