diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md
index 143dac89a96f92a03f173b5bf7c64715b59ccf52..1eb8c8343821d95aae1a2d2e12f33016bec752e0 100644
--- a/.github/PULL_REQUEST_TEMPLATE.md
+++ b/.github/PULL_REQUEST_TEMPLATE.md
@@ -1,3 +1,6 @@
+
+**Make sure set the target branch to `develop`**
+
## What is the purpose of the change
XXXXX
diff --git a/.travis.yml b/.travis.yml
index 34d38c2c54d5e87ee55ab2a10afa848444be3f30..df6a7356bffa1e505dd70b950bd6af0954d1d5ff 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 7f77f44e739b555b76538b83fe898a4d786c554d..f49a4e16e68b128803cc2dcea614603632b04eac 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 65ebdd036106a171f325936cdc0a907b0d6400c5..086ee9fa175f778d120c5dd4a7b81600595b51cf 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 9b28078f936269af1708ac86e84da8b71059c0fb..1b1398cb792644acc98420072c1ce844e5cac275 100644
--- a/README.md
+++ b/README.md
@@ -6,13 +6,13 @@
[![License](https://img.shields.io/badge/license-Apache%202-4EB1BA.svg)](https://www.apache.org/licenses/LICENSE-2.0.html)
[![Average time to resolve an issue](http://isitmaintained.com/badge/resolution/apache/rocketmq.svg)](http://isitmaintained.com/project/apache/rocketmq "Average time to resolve an issue")
[![Percentage of issues still open](http://isitmaintained.com/badge/open/apache/rocketmq.svg)](http://isitmaintained.com/project/apache/rocketmq "Percentage of issues still open")
-![Twitter Follow](https://img.shields.io/twitter/follow/ApacheRocketMQ?style=social)
+[![Twitter Follow](https://img.shields.io/twitter/follow/ApacheRocketMQ?style=social)](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.**
It offers a variety of features:
-* Messageing patterns including publish/subscribe, request/reply and streaming
+* Messaging patterns including publish/subscribe, request/reply and streaming
* Financial grade transactional message
* Built-in fault tolerance and high availability configuration options base on [DLedger](https://github.com/openmessaging/openmessaging-storage-dledger)
* A variety of cross language clients, such as Java, C/C++, Python, Go
diff --git a/acl/pom.xml b/acl/pom.xml
index bb91ac898823955c5235df6c06b11798bc5b3262..d62493417892e67b78a46f414f95320be263b6a7 100644
--- a/acl/pom.xml
+++ b/acl/pom.xml
@@ -13,15 +13,11 @@
org.apache.rocketmq
rocketmq-all
- 4.7.1-SNAPSHOT
+ 4.9.1-SNAPSHOT
rocketmq-acl
rocketmq-acl ${project.version}
- http://maven.apache.org
-
- UTF-8
-
${project.groupId}
@@ -62,11 +58,6 @@
logback-classic
test
-
- ch.qos.logback
- logback-core
- test
-
commons-validator
commons-validator
diff --git a/acl/src/main/java/org/apache/rocketmq/acl/common/AclConstants.java b/acl/src/main/java/org/apache/rocketmq/acl/common/AclConstants.java
index bfe96f53037cca259b837a461114f879b2b7359c..d129c66d1c81dbb0cbce7dc7d5324eacdd53864d 100644
--- a/acl/src/main/java/org/apache/rocketmq/acl/common/AclConstants.java
+++ b/acl/src/main/java/org/apache/rocketmq/acl/common/AclConstants.java
@@ -44,6 +44,16 @@ public class AclConstants {
public static final String CONFIG_TIME_STAMP = "timestamp";
+ public static final String PUB = "PUB";
+
+ public static final String SUB = "SUB";
+
+ public static final String DENY = "DENY";
+
+ public static final String PUB_SUB = "PUB|SUB";
+
+ public static final String SUB_PUB = "SUB|PUB";
+
public static final int ACCESS_KEY_MIN_LENGTH = 6;
public static final int SECRET_KEY_MIN_LENGTH = 6;
diff --git a/acl/src/main/java/org/apache/rocketmq/acl/common/AclUtils.java b/acl/src/main/java/org/apache/rocketmq/acl/common/AclUtils.java
index 8973320237c684c68864c29ff0c4a90d75bfdd3e..77abe0e80fbe734576e1b557a889f0e0a2afae47 100644
--- a/acl/src/main/java/org/apache/rocketmq/acl/common/AclUtils.java
+++ b/acl/src/main/java/org/apache/rocketmq/acl/common/AclUtils.java
@@ -94,7 +94,7 @@ public class AclUtils {
}
}
- public static String v6ipProcess(String netaddress, String[] strArray, int index) {
+ public static String v6ipProcess(String netaddress) {
int part;
String subAddress;
boolean isAsterisk = isAsterisk(netaddress);
@@ -120,7 +120,7 @@ public class AclUtils {
}
}
- public static String[] getAddreeStrArray(String netaddress, String partialAddress) {
+ public static String[] getAddresses(String netaddress, String partialAddress) {
String[] parAddStrArray = StringUtils.split(partialAddress.substring(1, partialAddress.length() - 1), ",");
String address = netaddress.substring(0, netaddress.indexOf("{"));
String[] addreeStrArray = new String[parAddStrArray.length];
diff --git a/acl/src/main/java/org/apache/rocketmq/acl/common/Permission.java b/acl/src/main/java/org/apache/rocketmq/acl/common/Permission.java
index 0acc8e9508138f3db3ae508dd5f78cd4a10011a2..dadcaa304aac45a460feb3e9a15654ffa46d6e8b 100644
--- a/acl/src/main/java/org/apache/rocketmq/acl/common/Permission.java
+++ b/acl/src/main/java/org/apache/rocketmq/acl/common/Permission.java
@@ -60,15 +60,14 @@ public class Permission {
return Permission.DENY;
}
switch (permString.trim()) {
- case "PUB":
+ case AclConstants.PUB:
return Permission.PUB;
- case "SUB":
+ case AclConstants.SUB:
return Permission.SUB;
- case "PUB|SUB":
+ case AclConstants.PUB_SUB:
+ case AclConstants.SUB_PUB:
return Permission.PUB | Permission.SUB;
- case "SUB|PUB":
- return Permission.PUB | Permission.SUB;
- case "DENY":
+ case AclConstants.DENY:
return Permission.DENY;
default:
return Permission.DENY;
@@ -90,6 +89,25 @@ public class Permission {
}
}
+ public static void checkResourcePerms(List resources) {
+ if (resources == null || resources.isEmpty()) {
+ return;
+ }
+
+ for (String resource : resources) {
+ String[] items = StringUtils.split(resource, "=");
+ if (items.length != 2) {
+ throw new AclException(String.format("Parse Resource format error for %s.\n" +
+ "The expected resource format is 'Res=Perm'. For example: topicA=SUB", resource));
+ }
+
+ if (!AclConstants.DENY.equals(items[1].trim()) && Permission.DENY == Permission.parsePermFromString(items[1].trim())) {
+ throw new AclException(String.format("Parse resource permission error for %s.\n" +
+ "The expected permissions are 'SUB' or 'PUB' or 'SUB|PUB' or 'PUB|SUB'.", resource));
+ }
+ }
+ }
+
public static boolean needAdminPerm(Integer code) {
return ADMIN_CODE.contains(code);
}
diff --git a/acl/src/main/java/org/apache/rocketmq/acl/plain/PlainPermissionManager.java b/acl/src/main/java/org/apache/rocketmq/acl/plain/PlainPermissionManager.java
index 89638f6ac2cdcc818537887fb77851cdb16f0b1e..078d34b10b02a84837ad6bb0b34dd884833cab9c 100644
--- a/acl/src/main/java/org/apache/rocketmq/acl/plain/PlainPermissionManager.java
+++ b/acl/src/main/java/org/apache/rocketmq/acl/plain/PlainPermissionManager.java
@@ -50,9 +50,9 @@ public class PlainPermissionManager {
private String fileName = System.getProperty("rocketmq.acl.plain.file", DEFAULT_PLAIN_ACL_FILE);
- private Map plainAccessResourceMap = new HashMap<>();
+ private Map plainAccessResourceMap = new HashMap<>();
- private List globalWhiteRemoteAddressStrategy = new ArrayList<>();
+ private List globalWhiteRemoteAddressStrategy = new ArrayList<>();
private RemoteAddressStrategyFactory remoteAddressStrategyFactory = new RemoteAddressStrategyFactory();
@@ -73,14 +73,14 @@ public class PlainPermissionManager {
JSONObject plainAclConfData = AclUtils.getYamlDataObject(fileHome + File.separator + fileName,
JSONObject.class);
if (plainAclConfData == null || plainAclConfData.isEmpty()) {
- throw new AclException(String.format("%s file is not data", fileHome + File.separator + fileName));
+ throw new AclException(String.format("%s file is not data", fileHome + File.separator + fileName));
}
log.info("Broker plain acl conf data is : ", plainAclConfData.toString());
JSONArray globalWhiteRemoteAddressesList = plainAclConfData.getJSONArray("globalWhiteRemoteAddresses");
if (globalWhiteRemoteAddressesList != null && !globalWhiteRemoteAddressesList.isEmpty()) {
for (int i = 0; i < globalWhiteRemoteAddressesList.size(); i++) {
globalWhiteRemoteAddressStrategy.add(remoteAddressStrategyFactory.
- getRemoteAddressStrategy(globalWhiteRemoteAddressesList.getString(i)));
+ getRemoteAddressStrategy(globalWhiteRemoteAddressesList.getString(i)));
}
}
@@ -89,7 +89,7 @@ public class PlainPermissionManager {
List plainAccessConfigList = accounts.toJavaList(PlainAccessConfig.class);
for (PlainAccessConfig plainAccessConfig : plainAccessConfigList) {
PlainAccessResource plainAccessResource = buildPlainAccessResource(plainAccessConfig);
- plainAccessResourceMap.put(plainAccessResource.getAccessKey(),plainAccessResource);
+ plainAccessResourceMap.put(plainAccessResource.getAccessKey(), plainAccessResource);
}
}
@@ -128,12 +128,17 @@ public class PlainPermissionManager {
if (plainAccessConfig == null) {
log.error("Parameter value plainAccessConfig is null,Please check your parameter");
- return false;
+ throw new AclException("Parameter value plainAccessConfig is null, Please check your parameter");
}
+ Permission.checkResourcePerms(plainAccessConfig.getTopicPerms());
+ Permission.checkResourcePerms(plainAccessConfig.getGroupPerms());
+
Map aclAccessConfigMap = AclUtils.getYamlDataObject(fileHome + File.separator + fileName,
Map.class);
-
+ if (aclAccessConfigMap == null || aclAccessConfigMap.isEmpty()) {
+ throw new AclException(String.format("the %s file is not found or empty", fileHome + File.separator + fileName));
+ }
List
-
- ch.qos.logback
- logback-core
-
com.alibaba
fastjson
diff --git a/broker/src/main/java/org/apache/rocketmq/broker/client/ProducerManager.java b/broker/src/main/java/org/apache/rocketmq/broker/client/ProducerManager.java
index 860b3493d1e97c93b178b48e9717aaf328510552..4bd00eff181e51655279166d026b58152e2c0d94 100644
--- a/broker/src/main/java/org/apache/rocketmq/broker/client/ProducerManager.java
+++ b/broker/src/main/java/org/apache/rocketmq/broker/client/ProducerManager.java
@@ -33,7 +33,7 @@ import org.apache.rocketmq.remoting.common.RemotingUtil;
public class ProducerManager {
private static final InternalLogger log = InternalLoggerFactory.getLogger(LoggerName.BROKER_LOGGER_NAME);
private static final long CHANNEL_EXPIRED_TIMEOUT = 1000 * 120;
- private static final int GET_AVALIABLE_CHANNEL_RETRY_COUNT = 3;
+ private static final int GET_AVAILABLE_CHANNEL_RETRY_COUNT = 3;
private final ConcurrentHashMap> groupChannelTable =
new ConcurrentHashMap<>();
private final ConcurrentHashMap clientChannelTable = new ConcurrentHashMap<>();
@@ -131,16 +131,14 @@ public class ProducerManager {
}
}
- public Channel getAvaliableChannel(String groupId) {
+ public Channel getAvailableChannel(String groupId) {
if (groupId == null) {
return null;
}
- List channelList = new ArrayList();
+ List channelList;
ConcurrentHashMap channelClientChannelInfoHashMap = groupChannelTable.get(groupId);
if (channelClientChannelInfoHashMap != null) {
- for (Channel channel : channelClientChannelInfoHashMap.keySet()) {
- channelList.add(channel);
- }
+ channelList = new ArrayList<>(channelClientChannelInfoHashMap.keySet());
} else {
log.warn("Check transaction failed, channel table is empty. groupId={}", groupId);
return null;
@@ -158,7 +156,7 @@ public class ProducerManager {
Channel channel = channelList.get(index);
int count = 0;
boolean isOk = channel.isActive() && channel.isWritable();
- while (count++ < GET_AVALIABLE_CHANNEL_RETRY_COUNT) {
+ while (count++ < GET_AVAILABLE_CHANNEL_RETRY_COUNT) {
if (isOk) {
return channel;
}
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 a74b6d66ce8517c08c608744ce489575da1e12cc..a89bace193e6fb64c60796172998a835bde4333e 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 ebc9dd8acce90512f1f0ddc17c62bbd866057729..bd0575875970f29fd4dc97d14bfcedbb762c2cab 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 6caa2358e32eb9ece9be1e14f3fc158b3406d034..de7f3fce81c7a70a7e9b0eeb1daa6a2f9dd68c4c 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
@@ -16,7 +16,6 @@
*/
package org.apache.rocketmq.broker.out;
-import com.google.common.collect.Lists;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;
@@ -123,7 +122,7 @@ public class BrokerOuterAPI {
final int timeoutMills,
final boolean compressed) {
- final List registerBrokerResultList = Lists.newArrayList();
+ 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);
}
@@ -209,7 +208,7 @@ public class BrokerOuterAPI {
break;
}
- throw new MQBrokerException(response.getCode(), response.getRemark());
+ throw new MQBrokerException(response.getCode(), response.getRemark(), requestHeader == null ? null : requestHeader.getBrokerAddr());
}
public void unregisterBrokerAll(
@@ -255,7 +254,7 @@ public class BrokerOuterAPI {
break;
}
- throw new MQBrokerException(response.getCode(), response.getRemark());
+ throw new MQBrokerException(response.getCode(), response.getRemark(), brokerAddr);
}
public List needRegister(
@@ -338,7 +337,7 @@ public class BrokerOuterAPI {
break;
}
- throw new MQBrokerException(response.getCode(), response.getRemark());
+ throw new MQBrokerException(response.getCode(), response.getRemark(), addr);
}
public ConsumerOffsetSerializeWrapper getAllConsumerOffset(
@@ -355,7 +354,7 @@ public class BrokerOuterAPI {
break;
}
- throw new MQBrokerException(response.getCode(), response.getRemark());
+ throw new MQBrokerException(response.getCode(), response.getRemark(), addr);
}
public String getAllDelayOffset(
@@ -372,7 +371,7 @@ public class BrokerOuterAPI {
break;
}
- throw new MQBrokerException(response.getCode(), response.getRemark());
+ throw new MQBrokerException(response.getCode(), response.getRemark(), addr);
}
public SubscriptionGroupWrapper getAllSubscriptionGroupConfig(
@@ -389,7 +388,7 @@ public class BrokerOuterAPI {
break;
}
- throw new MQBrokerException(response.getCode(), response.getRemark());
+ throw new MQBrokerException(response.getCode(), response.getRemark(), addr);
}
public void registerRPCHook(RPCHook rpcHook) {
diff --git a/broker/src/main/java/org/apache/rocketmq/broker/processor/AbstractSendMessageProcessor.java b/broker/src/main/java/org/apache/rocketmq/broker/processor/AbstractSendMessageProcessor.java
index 55b939201561f3645ebb5fff332b397c5d027ed4..ced7c2014f4a5d24b5832971142e686ebc404df0 100644
--- a/broker/src/main/java/org/apache/rocketmq/broker/processor/AbstractSendMessageProcessor.java
+++ b/broker/src/main/java/org/apache/rocketmq/broker/processor/AbstractSendMessageProcessor.java
@@ -25,7 +25,7 @@ import java.util.Random;
import org.apache.rocketmq.broker.BrokerController;
import org.apache.rocketmq.broker.mqtrace.SendMessageContext;
import org.apache.rocketmq.broker.mqtrace.SendMessageHook;
-import org.apache.rocketmq.broker.topic.TopicValidator;
+import org.apache.rocketmq.common.topic.TopicValidator;
import org.apache.rocketmq.common.MixAll;
import org.apache.rocketmq.common.TopicConfig;
import org.apache.rocketmq.common.TopicFilterType;
@@ -176,6 +176,9 @@ public abstract class AbstractSendMessageProcessor extends AsyncNettyRequestProc
if (!TopicValidator.validateTopic(requestHeader.getTopic(), response)) {
return response;
}
+ if (TopicValidator.isNotAllowedSendTopic(requestHeader.getTopic(), response)) {
+ return response;
+ }
TopicConfig topicConfig =
this.brokerController.getTopicConfigManager().selectTopicConfig(requestHeader.getTopic());
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 eb811832058e8343df8aafcbc0e78a96a3106618..97ca51d966d38b18bfdfb430c707a093b2e41a42 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
@@ -19,17 +19,6 @@ package org.apache.rocketmq.broker.processor;
import com.alibaba.fastjson.JSON;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
-import java.io.UnsupportedEncodingException;
-import java.net.UnknownHostException;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Properties;
-import java.util.Set;
-import java.util.concurrent.ConcurrentMap;
import org.apache.rocketmq.acl.AccessValidator;
import org.apache.rocketmq.acl.plain.PlainAccessValidator;
import org.apache.rocketmq.broker.BrokerController;
@@ -37,8 +26,8 @@ import org.apache.rocketmq.broker.client.ClientChannelInfo;
import org.apache.rocketmq.broker.client.ConsumerGroupInfo;
import org.apache.rocketmq.broker.filter.ConsumerFilterData;
import org.apache.rocketmq.broker.filter.ExpressionMessageFilter;
+import org.apache.rocketmq.common.topic.TopicValidator;
import org.apache.rocketmq.broker.transaction.queue.TransactionalMessageUtil;
-import org.apache.rocketmq.broker.topic.TopicValidator;
import org.apache.rocketmq.common.AclConfig;
import org.apache.rocketmq.common.MQVersion;
import org.apache.rocketmq.common.MixAll;
@@ -127,6 +116,7 @@ import org.apache.rocketmq.remoting.netty.NettyRequestProcessor;
import org.apache.rocketmq.remoting.protocol.LanguageCode;
import org.apache.rocketmq.remoting.protocol.RemotingCommand;
import org.apache.rocketmq.remoting.protocol.RemotingSerializable;
+import org.apache.rocketmq.remoting.protocol.RemotingSysResponseCode;
import org.apache.rocketmq.store.ConsumeQueue;
import org.apache.rocketmq.store.ConsumeQueueExt;
import org.apache.rocketmq.store.DefaultMessageStore;
@@ -137,6 +127,18 @@ import org.apache.rocketmq.store.PutMessageResult;
import org.apache.rocketmq.store.PutMessageStatus;
import org.apache.rocketmq.store.SelectMappedBufferResult;
+import java.io.UnsupportedEncodingException;
+import java.net.UnknownHostException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+import java.util.concurrent.ConcurrentMap;
+
public class AdminBrokerProcessor extends AsyncNettyRequestProcessor implements NettyRequestProcessor {
private static final InternalLogger log = InternalLoggerFactory.getLogger(LoggerName.BROKER_LOGGER_NAME);
private final BrokerController brokerController;
@@ -234,10 +236,8 @@ public class AdminBrokerProcessor extends AsyncNettyRequestProcessor implements
case RequestCode.GET_BROKER_CLUSTER_ACL_CONFIG:
return getBrokerClusterAclConfig(ctx, request);
default:
- break;
+ return getUnknownCmdResponse(ctx, request);
}
-
- return null;
}
@Override
@@ -252,29 +252,16 @@ public class AdminBrokerProcessor extends AsyncNettyRequestProcessor implements
(CreateTopicRequestHeader) request.decodeCommandCustomHeader(CreateTopicRequestHeader.class);
log.info("updateAndCreateTopic called by {}", RemotingHelper.parseChannelRemoteAddr(ctx.channel()));
- if (requestHeader.getTopic().equals(this.brokerController.getBrokerConfig().getBrokerClusterName())) {
- String errorMsg = "the topic[" + requestHeader.getTopic() + "] is conflict with system reserved words.";
- log.warn(errorMsg);
- response.setCode(ResponseCode.SYSTEM_ERROR);
- response.setRemark(errorMsg);
- return response;
- }
+ String topic = requestHeader.getTopic();
- if (!TopicValidator.validateTopic(requestHeader.getTopic(), response)) {
+ if (!TopicValidator.validateTopic(topic, response)) {
return response;
}
-
- try {
- response.setCode(ResponseCode.SUCCESS);
- response.setOpaque(request.getOpaque());
- response.markResponseType();
- response.setRemark(null);
- ctx.writeAndFlush(response);
- } catch (Exception e) {
- log.error("Failed to produce a proper response", e);
+ if (TopicValidator.isSystemTopic(topic, response)) {
+ return response;
}
- TopicConfig topicConfig = new TopicConfig(requestHeader.getTopic());
+ TopicConfig topicConfig = new TopicConfig(topic);
topicConfig.setReadQueueNums(requestHeader.getReadQueueNums());
topicConfig.setWriteQueueNums(requestHeader.getWriteQueueNums());
topicConfig.setTopicFilterType(requestHeader.getTopicFilterTypeEnum());
@@ -285,7 +272,8 @@ public class AdminBrokerProcessor extends AsyncNettyRequestProcessor implements
this.brokerController.registerIncrementBrokerData(topicConfig, this.brokerController.getTopicConfigManager().getDataVersion());
- return null;
+ response.setCode(ResponseCode.SUCCESS);
+ return response;
}
private synchronized RemotingCommand deleteTopic(ChannelHandlerContext ctx,
@@ -296,7 +284,15 @@ public class AdminBrokerProcessor extends AsyncNettyRequestProcessor implements
log.info("deleteTopic called by {}", RemotingHelper.parseChannelRemoteAddr(ctx.channel()));
- this.brokerController.getTopicConfigManager().deleteTopicConfig(requestHeader.getTopic());
+ String topic = requestHeader.getTopic();
+ if (!TopicValidator.validateTopic(topic, response)) {
+ return response;
+ }
+ if (TopicValidator.isSystemTopic(topic, response)) {
+ return response;
+ }
+
+ this.brokerController.getTopicConfigManager().deleteTopicConfig(topic);
this.brokerController.getMessageStore()
.cleanUnusedTopic(this.brokerController.getTopicConfigManager().getTopicConfigTable().keySet());
if (this.brokerController.getBrokerConfig().isAutoDeleteUnusedStats()) {
@@ -430,7 +426,7 @@ public class AdminBrokerProcessor extends AsyncNettyRequestProcessor implements
responseHeader.setBrokerAddr(this.brokerController.getBrokerAddr());
responseHeader.setBrokerName(this.brokerController.getBrokerConfig().getBrokerName());
responseHeader.setClusterName(this.brokerController.getBrokerConfig().getBrokerClusterName());
-
+
response.setCode(ResponseCode.SUCCESS);
response.setRemark(null);
return response;
@@ -462,6 +458,13 @@ public class AdminBrokerProcessor extends AsyncNettyRequestProcessor implements
return null;
}
+ private RemotingCommand getUnknownCmdResponse(ChannelHandlerContext ctx, RemotingCommand request) {
+ String error = " request type " + request.getCode() + " not supported";
+ final RemotingCommand response =
+ RemotingCommand.createResponseCommand(RemotingSysResponseCode.REQUEST_CODE_NOT_SUPPORTED, error);
+ return response;
+ }
+
private RemotingCommand getAllTopicConfig(ChannelHandlerContext ctx, RemotingCommand request) {
final RemotingCommand response = RemotingCommand.createResponseCommand(GetAllTopicConfigResponseHeader.class);
// final GetAllTopicConfigResponseHeader responseHeader =
@@ -717,6 +720,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());
}
@@ -1118,7 +1125,7 @@ public class AdminBrokerProcessor extends AsyncNettyRequestProcessor implements
throws RemotingCommandException {
final RemotingCommand response = RemotingCommand.createResponseCommand(null);
- Set topics = this.brokerController.getTopicConfigManager().getSystemTopic();
+ Set topics = TopicValidator.getSystemTopicSet();
TopicList topicList = new TopicList();
topicList.setTopicList(topics);
response.setBody(topicList.encode());
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 b02b5a058838a5eb6305d5f65cd856213536a805..8879a722fcf1967fd013aea6730c48bda6cf5c5c 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
@@ -52,6 +52,7 @@ import org.apache.rocketmq.common.protocol.topic.OffsetMovedEvent;
import org.apache.rocketmq.common.subscription.SubscriptionGroupConfig;
import org.apache.rocketmq.common.sysflag.MessageSysFlag;
import org.apache.rocketmq.common.sysflag.PullSysFlag;
+import org.apache.rocketmq.common.topic.TopicValidator;
import org.apache.rocketmq.logging.InternalLogger;
import org.apache.rocketmq.logging.InternalLoggerFactory;
import org.apache.rocketmq.remoting.common.RemotingHelper;
@@ -523,7 +524,7 @@ public class PullMessageProcessor extends AsyncNettyRequestProcessor implements
private void generateOffsetMovedEvent(final OffsetMovedEvent event) {
try {
MessageExtBrokerInner msgInner = new MessageExtBrokerInner();
- msgInner.setTopic(MixAll.OFFSET_MOVED_EVENT);
+ msgInner.setTopic(TopicValidator.RMQ_SYS_OFFSET_MOVED_EVENT);
msgInner.setTags(event.getConsumerGroup());
msgInner.setDelayTimeLevel(0);
msgInner.setKeys(event.getConsumerGroup());
@@ -583,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 565857a34779c126154694f0ac6b0881d60d5007..2890fc4db753d922bc2ba7520e6f2f0217ae4f5c 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 20b5cfaae829351d6d89496540f9bd5bb71d14f1..724cf54c8137c57d1dd8a5d434e20e582674d7a7 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 199b46d603a72ffb4561d21a6e146df291228390..1f2bb4d8ba49c00a4b10a0f674bd05aaf9aaa7a2 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
@@ -16,7 +16,6 @@
*/
package org.apache.rocketmq.broker.topic;
-import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
@@ -37,18 +36,20 @@ import org.apache.rocketmq.common.constant.PermName;
import org.apache.rocketmq.common.protocol.body.KVTable;
import org.apache.rocketmq.common.protocol.body.TopicConfigSerializeWrapper;
import org.apache.rocketmq.common.sysflag.TopicSysFlag;
+import org.apache.rocketmq.common.topic.TopicValidator;
import org.apache.rocketmq.logging.InternalLogger;
import org.apache.rocketmq.logging.InternalLoggerFactory;
public class TopicConfigManager extends ConfigManager {
private static final InternalLogger log = InternalLoggerFactory.getLogger(LoggerName.BROKER_LOGGER_NAME);
private static final long LOCK_TIMEOUT_MILLIS = 3000;
- private transient final Lock lockTopicConfigTable = new ReentrantLock();
+ private static final int SCHEDULE_TOPIC_QUEUE_NUM = 18;
+
+ private transient final Lock topicConfigTableLock = new ReentrantLock();
private final ConcurrentMap topicConfigTable =
new ConcurrentHashMap(1024);
private final DataVersion dataVersion = new DataVersion();
- private final Set systemTopicList = new HashSet();
private transient BrokerController brokerController;
public TopicConfigManager() {
@@ -57,20 +58,18 @@ public class TopicConfigManager extends ConfigManager {
public TopicConfigManager(BrokerController brokerController) {
this.brokerController = brokerController;
{
- // MixAll.SELF_TEST_TOPIC
- String topic = MixAll.SELF_TEST_TOPIC;
+ String topic = TopicValidator.RMQ_SYS_SELF_TEST_TOPIC;
TopicConfig topicConfig = new TopicConfig(topic);
- this.systemTopicList.add(topic);
+ TopicValidator.addSystemTopic(topic);
topicConfig.setReadQueueNums(1);
topicConfig.setWriteQueueNums(1);
this.topicConfigTable.put(topicConfig.getTopicName(), topicConfig);
}
{
- // MixAll.AUTO_CREATE_TOPIC_KEY_TOPIC
if (this.brokerController.getBrokerConfig().isAutoCreateTopicEnable()) {
- String topic = MixAll.AUTO_CREATE_TOPIC_KEY_TOPIC;
+ String topic = TopicValidator.AUTO_CREATE_TOPIC_KEY_TOPIC;
TopicConfig topicConfig = new TopicConfig(topic);
- this.systemTopicList.add(topic);
+ TopicValidator.addSystemTopic(topic);
topicConfig.setReadQueueNums(this.brokerController.getBrokerConfig()
.getDefaultTopicQueueNums());
topicConfig.setWriteQueueNums(this.brokerController.getBrokerConfig()
@@ -81,10 +80,9 @@ public class TopicConfigManager extends ConfigManager {
}
}
{
- // MixAll.BENCHMARK_TOPIC
- String topic = MixAll.BENCHMARK_TOPIC;
+ String topic = TopicValidator.RMQ_SYS_BENCHMARK_TOPIC;
TopicConfig topicConfig = new TopicConfig(topic);
- this.systemTopicList.add(topic);
+ TopicValidator.addSystemTopic(topic);
topicConfig.setReadQueueNums(1024);
topicConfig.setWriteQueueNums(1024);
this.topicConfigTable.put(topicConfig.getTopicName(), topicConfig);
@@ -93,7 +91,7 @@ public class TopicConfigManager extends ConfigManager {
String topic = this.brokerController.getBrokerConfig().getBrokerClusterName();
TopicConfig topicConfig = new TopicConfig(topic);
- this.systemTopicList.add(topic);
+ TopicValidator.addSystemTopic(topic);
int perm = PermName.PERM_INHERIT;
if (this.brokerController.getBrokerConfig().isClusterTopicEnable()) {
perm |= PermName.PERM_READ | PermName.PERM_WRITE;
@@ -105,7 +103,7 @@ public class TopicConfigManager extends ConfigManager {
String topic = this.brokerController.getBrokerConfig().getBrokerName();
TopicConfig topicConfig = new TopicConfig(topic);
- this.systemTopicList.add(topic);
+ TopicValidator.addSystemTopic(topic);
int perm = PermName.PERM_INHERIT;
if (this.brokerController.getBrokerConfig().isBrokerTopicEnable()) {
perm |= PermName.PERM_READ | PermName.PERM_WRITE;
@@ -116,19 +114,26 @@ public class TopicConfigManager extends ConfigManager {
this.topicConfigTable.put(topicConfig.getTopicName(), topicConfig);
}
{
- // MixAll.OFFSET_MOVED_EVENT
- String topic = MixAll.OFFSET_MOVED_EVENT;
+ String topic = TopicValidator.RMQ_SYS_OFFSET_MOVED_EVENT;
TopicConfig topicConfig = new TopicConfig(topic);
- this.systemTopicList.add(topic);
+ TopicValidator.addSystemTopic(topic);
topicConfig.setReadQueueNums(1);
topicConfig.setWriteQueueNums(1);
this.topicConfigTable.put(topicConfig.getTopicName(), topicConfig);
}
+ {
+ String topic = TopicValidator.RMQ_SYS_SCHEDULE_TOPIC;
+ TopicConfig topicConfig = new TopicConfig(topic);
+ TopicValidator.addSystemTopic(topic);
+ topicConfig.setReadQueueNums(SCHEDULE_TOPIC_QUEUE_NUM);
+ topicConfig.setWriteQueueNums(SCHEDULE_TOPIC_QUEUE_NUM);
+ this.topicConfigTable.put(topicConfig.getTopicName(), topicConfig);
+ }
{
if (this.brokerController.getBrokerConfig().isTraceTopicEnable()) {
String topic = this.brokerController.getBrokerConfig().getMsgTraceTopicName();
TopicConfig topicConfig = new TopicConfig(topic);
- this.systemTopicList.add(topic);
+ TopicValidator.addSystemTopic(topic);
topicConfig.setReadQueueNums(1);
topicConfig.setWriteQueueNums(1);
this.topicConfigTable.put(topicConfig.getTopicName(), topicConfig);
@@ -137,21 +142,13 @@ public class TopicConfigManager extends ConfigManager {
{
String topic = this.brokerController.getBrokerConfig().getBrokerClusterName() + "_" + MixAll.REPLY_TOPIC_POSTFIX;
TopicConfig topicConfig = new TopicConfig(topic);
- this.systemTopicList.add(topic);
+ TopicValidator.addSystemTopic(topic);
topicConfig.setReadQueueNums(1);
topicConfig.setWriteQueueNums(1);
this.topicConfigTable.put(topicConfig.getTopicName(), topicConfig);
}
}
- public boolean isSystemTopic(final String topic) {
- return this.systemTopicList.contains(topic);
- }
-
- public Set getSystemTopic() {
- return this.systemTopicList;
- }
-
public TopicConfig selectTopicConfig(final String topic) {
return this.topicConfigTable.get(topic);
}
@@ -162,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)
@@ -170,7 +167,7 @@ public class TopicConfigManager extends ConfigManager {
TopicConfig defaultTopicConfig = this.topicConfigTable.get(defaultTopic);
if (defaultTopicConfig != null) {
- if (defaultTopic.equals(MixAll.AUTO_CREATE_TOPIC_KEY_TOPIC)) {
+ if (defaultTopic.equals(TopicValidator.AUTO_CREATE_TOPIC_KEY_TOPIC)) {
if (!this.brokerController.getBrokerConfig().isAutoCreateTopicEnable()) {
defaultTopicConfig.setPerm(PermName.PERM_READ | PermName.PERM_WRITE);
}
@@ -179,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;
@@ -216,7 +211,7 @@ public class TopicConfigManager extends ConfigManager {
this.persist();
}
} finally {
- this.lockTopicConfigTable.unlock();
+ this.topicConfigTableLock.unlock();
}
}
} catch (InterruptedException e) {
@@ -242,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)
@@ -260,7 +255,7 @@ public class TopicConfigManager extends ConfigManager {
this.dataVersion.nextVersion();
this.persist();
} finally {
- this.lockTopicConfigTable.unlock();
+ this.topicConfigTableLock.unlock();
}
}
} catch (InterruptedException e) {
@@ -275,32 +270,32 @@ public class TopicConfigManager extends ConfigManager {
}
public TopicConfig createTopicOfTranCheckMaxTime(final int clientDefaultTopicQueueNums, final int perm) {
- TopicConfig topicConfig = this.topicConfigTable.get(MixAll.TRANS_CHECK_MAX_TIME_TOPIC);
+ TopicConfig topicConfig = this.topicConfigTable.get(TopicValidator.RMQ_SYS_TRANS_CHECK_MAX_TIME_TOPIC);
if (topicConfig != null)
return topicConfig;
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(MixAll.TRANS_CHECK_MAX_TIME_TOPIC);
+ topicConfig = this.topicConfigTable.get(TopicValidator.RMQ_SYS_TRANS_CHECK_MAX_TIME_TOPIC);
if (topicConfig != null)
return topicConfig;
- topicConfig = new TopicConfig(MixAll.TRANS_CHECK_MAX_TIME_TOPIC);
+ topicConfig = new TopicConfig(TopicValidator.RMQ_SYS_TRANS_CHECK_MAX_TIME_TOPIC);
topicConfig.setReadQueueNums(clientDefaultTopicQueueNums);
topicConfig.setWriteQueueNums(clientDefaultTopicQueueNums);
topicConfig.setPerm(perm);
topicConfig.setTopicSysFlag(0);
log.info("create new topic {}", topicConfig);
- this.topicConfigTable.put(MixAll.TRANS_CHECK_MAX_TIME_TOPIC, topicConfig);
+ this.topicConfigTable.put(TopicValidator.RMQ_SYS_TRANS_CHECK_MAX_TIME_TOPIC, topicConfig);
createNew = true;
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/topic/TopicValidator.java b/broker/src/main/java/org/apache/rocketmq/broker/topic/TopicValidator.java
deleted file mode 100644
index 58b1cc86fcdfcdbf38d3c3f9656008fae052b8c6..0000000000000000000000000000000000000000
--- a/broker/src/main/java/org/apache/rocketmq/broker/topic/TopicValidator.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * 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.broker.topic;
-
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-import org.apache.rocketmq.common.MixAll;
-import org.apache.rocketmq.common.UtilAll;
-import org.apache.rocketmq.common.protocol.ResponseCode;
-import org.apache.rocketmq.remoting.protocol.RemotingCommand;
-
-public class TopicValidator {
-
- private static final String VALID_PATTERN_STR = "^[%|a-zA-Z0-9_-]+$";
- private static final Pattern PATTERN = Pattern.compile(VALID_PATTERN_STR);
- private static final int TOPIC_MAX_LENGTH = 127;
-
- private static boolean regularExpressionMatcher(String origin, Pattern pattern) {
- if (pattern == null) {
- return true;
- }
- Matcher matcher = pattern.matcher(origin);
- return matcher.matches();
- }
-
- public static boolean validateTopic(String topic, RemotingCommand response) {
-
- if (UtilAll.isBlank(topic)) {
- response.setCode(ResponseCode.SYSTEM_ERROR);
- response.setRemark("The specified topic is blank.");
- return false;
- }
-
- if (!regularExpressionMatcher(topic, PATTERN)) {
- response.setCode(ResponseCode.SYSTEM_ERROR);
- response.setRemark("The specified topic contains illegal characters, allowing only " + VALID_PATTERN_STR);
- return false;
- }
-
- if (topic.length() > TOPIC_MAX_LENGTH) {
- response.setCode(ResponseCode.SYSTEM_ERROR);
- response.setRemark("The specified topic is longer than topic max length.");
- return false;
- }
-
- //whether the same with system reserved keyword
- if (topic.equals(MixAll.AUTO_CREATE_TOPIC_KEY_TOPIC)) {
- response.setCode(ResponseCode.SYSTEM_ERROR);
- response.setRemark("The specified topic is conflict with AUTO_CREATE_TOPIC_KEY_TOPIC.");
- return false;
- }
-
- return true;
- }
-}
diff --git a/broker/src/main/java/org/apache/rocketmq/broker/transaction/AbstractTransactionalMessageCheckListener.java b/broker/src/main/java/org/apache/rocketmq/broker/transaction/AbstractTransactionalMessageCheckListener.java
index 35d811207ba6687949877daa251730c3f26c77f6..4cf5647084da6f537dd60769ee980805acb7cffa 100644
--- a/broker/src/main/java/org/apache/rocketmq/broker/transaction/AbstractTransactionalMessageCheckListener.java
+++ b/broker/src/main/java/org/apache/rocketmq/broker/transaction/AbstractTransactionalMessageCheckListener.java
@@ -69,7 +69,7 @@ public abstract class AbstractTransactionalMessageCheckListener {
msgExt.setQueueId(Integer.parseInt(msgExt.getUserProperty(MessageConst.PROPERTY_REAL_QUEUE_ID)));
msgExt.setStoreSize(0);
String groupId = msgExt.getProperty(MessageConst.PROPERTY_PRODUCER_GROUP);
- Channel channel = brokerController.getProducerManager().getAvaliableChannel(groupId);
+ Channel channel = brokerController.getProducerManager().getAvailableChannel(groupId);
if (channel != null) {
brokerController.getBroker2Client().checkProducerTransactionState(groupId, channel, checkTransactionStateRequestHeader, msgExt);
} else {
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 25065ebe885f5644aa128f96e09a6583ad0ede65..74df47a088eab5bfcb41daeac6de8582c3fe568e 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
@@ -21,13 +21,13 @@ import org.apache.rocketmq.broker.transaction.OperationResult;
import org.apache.rocketmq.broker.transaction.TransactionalMessageService;
import org.apache.rocketmq.client.consumer.PullResult;
import org.apache.rocketmq.client.consumer.PullStatus;
-import org.apache.rocketmq.common.MixAll;
import org.apache.rocketmq.common.constant.LoggerName;
import org.apache.rocketmq.common.message.MessageConst;
import org.apache.rocketmq.common.message.MessageExt;
import org.apache.rocketmq.common.message.MessageQueue;
import org.apache.rocketmq.common.protocol.ResponseCode;
import org.apache.rocketmq.common.protocol.header.EndTransactionRequestHeader;
+import org.apache.rocketmq.common.topic.TopicValidator;
import org.apache.rocketmq.logging.InternalLogger;
import org.apache.rocketmq.logging.InternalLoggerFactory;
import org.apache.rocketmq.store.MessageExtBrokerInner;
@@ -127,7 +127,7 @@ public class TransactionalMessageServiceImpl implements TransactionalMessageServ
public void check(long transactionTimeout, int transactionCheckMax,
AbstractTransactionalMessageCheckListener listener) {
try {
- String topic = MixAll.RMQ_SYS_TRANS_HALF_TOPIC;
+ String topic = TopicValidator.RMQ_SYS_TRANS_HALF_TOPIC;
Set msgQueues = transactionalMessageBridge.fetchMessageQueues(topic);
if (msgQueues == null || msgQueues.size() == 0) {
log.warn("The queue of topic is empty :" + topic);
@@ -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/main/java/org/apache/rocketmq/broker/transaction/queue/TransactionalMessageUtil.java b/broker/src/main/java/org/apache/rocketmq/broker/transaction/queue/TransactionalMessageUtil.java
index 3042b4c3e568479407178072bae798a8751a76cd..e6baf0266ccf431a249514b91565092f844541c9 100644
--- a/broker/src/main/java/org/apache/rocketmq/broker/transaction/queue/TransactionalMessageUtil.java
+++ b/broker/src/main/java/org/apache/rocketmq/broker/transaction/queue/TransactionalMessageUtil.java
@@ -17,6 +17,7 @@
package org.apache.rocketmq.broker.transaction.queue;
import org.apache.rocketmq.common.MixAll;
+import org.apache.rocketmq.common.topic.TopicValidator;
import java.nio.charset.Charset;
@@ -25,11 +26,11 @@ public class TransactionalMessageUtil {
public static Charset charset = Charset.forName("utf-8");
public static String buildOpTopic() {
- return MixAll.RMQ_SYS_TRANS_OP_HALF_TOPIC;
+ return TopicValidator.RMQ_SYS_TRANS_OP_HALF_TOPIC;
}
public static String buildHalfTopic() {
- return MixAll.RMQ_SYS_TRANS_HALF_TOPIC;
+ return TopicValidator.RMQ_SYS_TRANS_HALF_TOPIC;
}
public static String buildConsumerGroup() {
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 68d58ef4400ffb5028d8c1b667dcf8ddfc236d22..9ea1eeee31b9995f35890a8b06e8ff765690b8ef 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/broker/src/test/java/org/apache/rocketmq/broker/client/ProducerManagerTest.java b/broker/src/test/java/org/apache/rocketmq/broker/client/ProducerManagerTest.java
index 4791ab1f053be7fe648309e8cc0d84c35dcc0c82..6c794ac5d33904ba10a7d5a71ec3db22731787a7 100644
--- a/broker/src/test/java/org/apache/rocketmq/broker/client/ProducerManagerTest.java
+++ b/broker/src/test/java/org/apache/rocketmq/broker/client/ProducerManagerTest.java
@@ -110,20 +110,20 @@ public class ProducerManagerTest {
}
@Test
- public void testGetAvaliableChannel() {
+ public void testGetAvailableChannel() {
producerManager.registerProducer(group, clientInfo);
when(channel.isActive()).thenReturn(true);
when(channel.isWritable()).thenReturn(true);
- Channel c = producerManager.getAvaliableChannel(group);
+ Channel c = producerManager.getAvailableChannel(group);
assertThat(c).isSameAs(channel);
when(channel.isWritable()).thenReturn(false);
- c = producerManager.getAvaliableChannel(group);
+ c = producerManager.getAvailableChannel(group);
assertThat(c).isSameAs(channel);
when(channel.isActive()).thenReturn(false);
- c = producerManager.getAvaliableChannel(group);
+ c = producerManager.getAvailableChannel(group);
assertThat(c).isNull();
}
diff --git a/broker/src/test/java/org/apache/rocketmq/broker/processor/AdminBrokerProcessorTest.java b/broker/src/test/java/org/apache/rocketmq/broker/processor/AdminBrokerProcessorTest.java
index ec0a879c209c97d7c8ab2f63f254e343b0b62fba..2764761d39f68fa081a961479a02ce25825a4f2d 100644
--- a/broker/src/test/java/org/apache/rocketmq/broker/processor/AdminBrokerProcessorTest.java
+++ b/broker/src/test/java/org/apache/rocketmq/broker/processor/AdminBrokerProcessorTest.java
@@ -16,17 +16,22 @@
*/
package org.apache.rocketmq.broker.processor;
+import com.google.common.collect.Sets;
import io.netty.channel.ChannelHandlerContext;
-import java.net.UnknownHostException;
-import java.nio.ByteBuffer;
import org.apache.rocketmq.broker.BrokerController;
import org.apache.rocketmq.common.BrokerConfig;
+import org.apache.rocketmq.common.MixAll;
+import org.apache.rocketmq.common.TopicFilterType;
+import org.apache.rocketmq.common.constant.PermName;
import org.apache.rocketmq.common.message.MessageAccessor;
import org.apache.rocketmq.common.message.MessageConst;
import org.apache.rocketmq.common.message.MessageExt;
import org.apache.rocketmq.common.protocol.RequestCode;
import org.apache.rocketmq.common.protocol.ResponseCode;
+import org.apache.rocketmq.common.protocol.header.CreateTopicRequestHeader;
+import org.apache.rocketmq.common.protocol.header.DeleteTopicRequestHeader;
import org.apache.rocketmq.common.protocol.header.ResumeCheckHalfMessageRequestHeader;
+import org.apache.rocketmq.common.topic.TopicValidator;
import org.apache.rocketmq.remoting.exception.RemotingCommandException;
import org.apache.rocketmq.remoting.netty.NettyClientConfig;
import org.apache.rocketmq.remoting.netty.NettyServerConfig;
@@ -47,6 +52,10 @@ import org.mockito.Mock;
import org.mockito.Spy;
import org.mockito.junit.MockitoJUnitRunner;
+import java.net.UnknownHostException;
+import java.nio.ByteBuffer;
+import java.util.Set;
+
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.when;
@@ -61,17 +70,30 @@ public class AdminBrokerProcessorTest {
@Spy
private BrokerController
- brokerController = new BrokerController(new BrokerConfig(), new NettyServerConfig(), new NettyClientConfig(),
- new MessageStoreConfig());
+ brokerController = new BrokerController(new BrokerConfig(), new NettyServerConfig(), new NettyClientConfig(),
+ new MessageStoreConfig());
@Mock
private MessageStore messageStore;
+ private Set systemTopicSet;
@Before
public void init() {
brokerController.setMessageStore(messageStore);
adminBrokerProcessor = new AdminBrokerProcessor(brokerController);
+
+ systemTopicSet = Sets.newHashSet(
+ TopicValidator.RMQ_SYS_SELF_TEST_TOPIC,
+ TopicValidator.RMQ_SYS_BENCHMARK_TOPIC,
+ TopicValidator.RMQ_SYS_SCHEDULE_TOPIC,
+ TopicValidator.RMQ_SYS_OFFSET_MOVED_EVENT,
+ TopicValidator.AUTO_CREATE_TOPIC_KEY_TOPIC,
+ this.brokerController.getBrokerConfig().getBrokerClusterName(),
+ this.brokerController.getBrokerConfig().getBrokerClusterName() + "_" + MixAll.REPLY_TOPIC_POSTFIX);
+ if (this.brokerController.getBrokerConfig().isTraceTopicEnable()) {
+ systemTopicSet.add(this.brokerController.getBrokerConfig().getMsgTraceTopicName());
+ }
}
@Test
@@ -94,6 +116,67 @@ public class AdminBrokerProcessorTest {
assertThat(response.getCode()).isEqualTo(ResponseCode.SYSTEM_ERROR);
}
+ @Test
+ public void testUpdateAndCreateTopic() throws Exception {
+ //test system topic
+ for (String topic : systemTopicSet) {
+ RemotingCommand request = buildCreateTopicRequest(topic);
+ RemotingCommand response = adminBrokerProcessor.processRequest(handlerContext, request);
+ assertThat(response.getCode()).isEqualTo(ResponseCode.SYSTEM_ERROR);
+ assertThat(response.getRemark()).isEqualTo("The topic[" + topic + "] is conflict with system topic.");
+ }
+
+ //test validate error topic
+ String topic = "";
+ RemotingCommand request = buildCreateTopicRequest(topic);
+ RemotingCommand response = adminBrokerProcessor.processRequest(handlerContext, request);
+ assertThat(response.getCode()).isEqualTo(ResponseCode.SYSTEM_ERROR);
+
+ topic = "TEST_CREATE_TOPIC";
+ request = buildCreateTopicRequest(topic);
+ response = adminBrokerProcessor.processRequest(handlerContext, request);
+ assertThat(response.getCode()).isEqualTo(ResponseCode.SUCCESS);
+
+ }
+
+ @Test
+ public void testDeleteTopic() throws Exception {
+ //test system topic
+ for (String topic : systemTopicSet) {
+ RemotingCommand request = buildDeleteTopicRequest(topic);
+ RemotingCommand response = adminBrokerProcessor.processRequest(handlerContext, request);
+ assertThat(response.getCode()).isEqualTo(ResponseCode.SYSTEM_ERROR);
+ assertThat(response.getRemark()).isEqualTo("The topic[" + topic + "] is conflict with system topic.");
+ }
+
+ String topic = "TEST_DELETE_TOPIC";
+ RemotingCommand request = buildDeleteTopicRequest(topic);
+ RemotingCommand response = adminBrokerProcessor.processRequest(handlerContext, request);
+ assertThat(response.getCode()).isEqualTo(ResponseCode.SUCCESS);
+ }
+
+ private RemotingCommand buildCreateTopicRequest(String topic) {
+ CreateTopicRequestHeader requestHeader = new CreateTopicRequestHeader();
+ requestHeader.setTopic(topic);
+ requestHeader.setTopicFilterType(TopicFilterType.SINGLE_TAG.name());
+ requestHeader.setReadQueueNums(8);
+ requestHeader.setWriteQueueNums(8);
+ requestHeader.setPerm(PermName.PERM_READ | PermName.PERM_WRITE);
+
+ RemotingCommand request = RemotingCommand.createRequestCommand(RequestCode.UPDATE_AND_CREATE_TOPIC, requestHeader);
+ request.makeCustomHeaderToNet();
+ return request;
+ }
+
+ private RemotingCommand buildDeleteTopicRequest(String topic) {
+ DeleteTopicRequestHeader requestHeader = new DeleteTopicRequestHeader();
+ requestHeader.setTopic(topic);
+
+ RemotingCommand request = RemotingCommand.createRequestCommand(RequestCode.DELETE_TOPIC_IN_BROKER, requestHeader);
+ request.makeCustomHeaderToNet();
+ return request;
+ }
+
private MessageExt createDefaultMessageExt() {
MessageExt messageExt = new MessageExt();
messageExt.setMsgId("12345678");
@@ -106,10 +189,11 @@ public class AdminBrokerProcessorTest {
return messageExt;
}
- private SelectMappedBufferResult createSelectMappedBufferResult(){
- SelectMappedBufferResult result = new SelectMappedBufferResult(0, ByteBuffer.allocate(1024) ,0, new MappedFile());
+ private SelectMappedBufferResult createSelectMappedBufferResult() {
+ SelectMappedBufferResult result = new SelectMappedBufferResult(0, ByteBuffer.allocate(1024), 0, new MappedFile());
return result;
}
+
private ResumeCheckHalfMessageRequestHeader createResumeCheckHalfMessageRequestHeader() {
ResumeCheckHalfMessageRequestHeader header = new ResumeCheckHalfMessageRequestHeader();
header.setMsgId("C0A803CA00002A9F0000000000031367");
diff --git a/broker/src/test/java/org/apache/rocketmq/broker/processor/ReplyMessageProcessorTest.java b/broker/src/test/java/org/apache/rocketmq/broker/processor/ReplyMessageProcessorTest.java
index 85c775040f53ef6093e979c8c6adc53a3a36161f..eeca6e7622c5d5e37bc7be493adcc9df668e5eab 100644
--- a/broker/src/test/java/org/apache/rocketmq/broker/processor/ReplyMessageProcessorTest.java
+++ b/broker/src/test/java/org/apache/rocketmq/broker/processor/ReplyMessageProcessorTest.java
@@ -25,15 +25,14 @@ import java.util.Map;
import org.apache.rocketmq.broker.BrokerController;
import org.apache.rocketmq.broker.client.ClientChannelInfo;
import org.apache.rocketmq.broker.client.net.Broker2Client;
-import org.apache.rocketmq.broker.transaction.TransactionalMessageService;
import org.apache.rocketmq.common.BrokerConfig;
-import org.apache.rocketmq.common.MixAll;
import org.apache.rocketmq.common.message.MessageConst;
import org.apache.rocketmq.common.message.MessageDecoder;
import org.apache.rocketmq.common.protocol.RequestCode;
import org.apache.rocketmq.common.protocol.ResponseCode;
import org.apache.rocketmq.common.protocol.header.SendMessageRequestHeader;
import org.apache.rocketmq.common.protocol.header.SendMessageResponseHeader;
+import org.apache.rocketmq.common.topic.TopicValidator;
import org.apache.rocketmq.remoting.exception.RemotingCommandException;
import org.apache.rocketmq.remoting.exception.RemotingSendRequestException;
import org.apache.rocketmq.remoting.exception.RemotingTimeoutException;
@@ -115,7 +114,7 @@ public class ReplyMessageProcessorTest {
SendMessageRequestHeader requestHeader = new SendMessageRequestHeader();
requestHeader.setProducerGroup(group);
requestHeader.setTopic(topic);
- requestHeader.setDefaultTopic(MixAll.AUTO_CREATE_TOPIC_KEY_TOPIC);
+ requestHeader.setDefaultTopic(TopicValidator.AUTO_CREATE_TOPIC_KEY_TOPIC);
requestHeader.setDefaultTopicQueueNums(3);
requestHeader.setQueueId(1);
requestHeader.setSysFlag(0);
diff --git a/broker/src/test/java/org/apache/rocketmq/broker/processor/SendMessageProcessorTest.java b/broker/src/test/java/org/apache/rocketmq/broker/processor/SendMessageProcessorTest.java
index bdf13d4a7faa7334861df540d9e5910996ad4b0a..b9344e90ed600f29ac72c2720b60fbbff1cda5d4 100644
--- a/broker/src/test/java/org/apache/rocketmq/broker/processor/SendMessageProcessorTest.java
+++ b/broker/src/test/java/org/apache/rocketmq/broker/processor/SendMessageProcessorTest.java
@@ -23,7 +23,6 @@ import org.apache.rocketmq.broker.mqtrace.SendMessageContext;
import org.apache.rocketmq.broker.mqtrace.SendMessageHook;
import org.apache.rocketmq.broker.transaction.TransactionalMessageService;
import org.apache.rocketmq.common.BrokerConfig;
-import org.apache.rocketmq.common.MixAll;
import org.apache.rocketmq.common.message.MessageConst;
import org.apache.rocketmq.common.message.MessageDecoder;
import org.apache.rocketmq.common.message.MessageExt;
@@ -32,6 +31,7 @@ import org.apache.rocketmq.common.protocol.ResponseCode;
import org.apache.rocketmq.common.protocol.header.ConsumerSendMsgBackRequestHeader;
import org.apache.rocketmq.common.protocol.header.SendMessageRequestHeader;
import org.apache.rocketmq.common.sysflag.MessageSysFlag;
+import org.apache.rocketmq.common.topic.TopicValidator;
import org.apache.rocketmq.remoting.exception.RemotingCommandException;
import org.apache.rocketmq.remoting.netty.NettyClientConfig;
import org.apache.rocketmq.remoting.netty.NettyServerConfig;
@@ -238,7 +238,7 @@ public class SendMessageProcessorTest {
SendMessageRequestHeader requestHeader = new SendMessageRequestHeader();
requestHeader.setProducerGroup(group);
requestHeader.setTopic(topic);
- requestHeader.setDefaultTopic(MixAll.AUTO_CREATE_TOPIC_KEY_TOPIC);
+ requestHeader.setDefaultTopic(TopicValidator.AUTO_CREATE_TOPIC_KEY_TOPIC);
requestHeader.setDefaultTopicQueueNums(3);
requestHeader.setQueueId(1);
requestHeader.setSysFlag(0);
diff --git a/broker/src/test/java/org/apache/rocketmq/broker/transaction/queue/DefaultTransactionalMessageCheckListenerTest.java b/broker/src/test/java/org/apache/rocketmq/broker/transaction/queue/DefaultTransactionalMessageCheckListenerTest.java
index 653a96933ed5decb6b19a0086008c96d90ad7c77..f6035463c01a4588f69f7094d02a331416284b5a 100644
--- a/broker/src/test/java/org/apache/rocketmq/broker/transaction/queue/DefaultTransactionalMessageCheckListenerTest.java
+++ b/broker/src/test/java/org/apache/rocketmq/broker/transaction/queue/DefaultTransactionalMessageCheckListenerTest.java
@@ -19,10 +19,10 @@ package org.apache.rocketmq.broker.transaction.queue;
import java.net.InetSocketAddress;
import org.apache.rocketmq.broker.BrokerController;
import org.apache.rocketmq.common.BrokerConfig;
-import org.apache.rocketmq.common.MixAll;
import org.apache.rocketmq.common.message.MessageAccessor;
import org.apache.rocketmq.common.message.MessageConst;
import org.apache.rocketmq.common.message.MessageExt;
+import org.apache.rocketmq.common.topic.TopicValidator;
import org.apache.rocketmq.remoting.netty.NettyClientConfig;
import org.apache.rocketmq.remoting.netty.NettyServerConfig;
import org.apache.rocketmq.store.MessageExtBrokerInner;
@@ -92,7 +92,7 @@ public class DefaultTransactionalMessageCheckListenerTest {
@Test
public void testResolveDiscardMsg() {
MessageExt messageExt = new MessageExt();
- messageExt.setTopic(MixAll.RMQ_SYS_TRANS_HALF_TOPIC);
+ messageExt.setTopic(TopicValidator.RMQ_SYS_TRANS_HALF_TOPIC);
messageExt.setQueueId(0);
messageExt.setBody("test resolve discard msg".getBytes());
messageExt.setStoreHost(new InetSocketAddress("127.0.0.1", 10911));
diff --git a/broker/src/test/java/org/apache/rocketmq/broker/transaction/queue/TransactionalMessageBridgeTest.java b/broker/src/test/java/org/apache/rocketmq/broker/transaction/queue/TransactionalMessageBridgeTest.java
index 5d8c2b955d6cadac46eb8302a7d79bcaeb6951fa..031a55a5d9d74af1151896834d8f5d8656084894 100644
--- a/broker/src/test/java/org/apache/rocketmq/broker/transaction/queue/TransactionalMessageBridgeTest.java
+++ b/broker/src/test/java/org/apache/rocketmq/broker/transaction/queue/TransactionalMessageBridgeTest.java
@@ -20,11 +20,11 @@ import org.apache.rocketmq.broker.BrokerController;
import org.apache.rocketmq.client.consumer.PullResult;
import org.apache.rocketmq.client.consumer.PullStatus;
import org.apache.rocketmq.common.BrokerConfig;
-import org.apache.rocketmq.common.MixAll;
import org.apache.rocketmq.common.message.MessageAccessor;
import org.apache.rocketmq.common.message.MessageConst;
import org.apache.rocketmq.common.message.MessageExt;
import org.apache.rocketmq.common.message.MessageQueue;
+import org.apache.rocketmq.common.topic.TopicValidator;
import org.apache.rocketmq.remoting.netty.NettyClientConfig;
import org.apache.rocketmq.remoting.netty.NettyServerConfig;
import org.apache.rocketmq.store.AppendMessageResult;
@@ -98,7 +98,7 @@ public class TransactionalMessageBridgeTest {
@Test
public void testFetchMessageQueues() {
- Set messageQueues = transactionBridge.fetchMessageQueues(MixAll.RMQ_SYS_TRANS_HALF_TOPIC);
+ Set messageQueues = transactionBridge.fetchMessageQueues(TopicValidator.RMQ_SYS_TRANS_HALF_TOPIC);
assertThat(messageQueues.size()).isEqualTo(1);
}
diff --git a/broker/src/test/java/org/apache/rocketmq/broker/transaction/queue/TransactionalMessageServiceImplTest.java b/broker/src/test/java/org/apache/rocketmq/broker/transaction/queue/TransactionalMessageServiceImplTest.java
index 47eccbe026ee5f1e9a04092cc90d1af7f2e512b8..8b138fc896a5e929fbfa8f5e1f9b91d9cc139a98 100644
--- a/broker/src/test/java/org/apache/rocketmq/broker/transaction/queue/TransactionalMessageServiceImplTest.java
+++ b/broker/src/test/java/org/apache/rocketmq/broker/transaction/queue/TransactionalMessageServiceImplTest.java
@@ -23,13 +23,13 @@ import org.apache.rocketmq.broker.transaction.TransactionalMessageService;
import org.apache.rocketmq.client.consumer.PullResult;
import org.apache.rocketmq.client.consumer.PullStatus;
import org.apache.rocketmq.common.BrokerConfig;
-import org.apache.rocketmq.common.MixAll;
import org.apache.rocketmq.common.message.MessageConst;
import org.apache.rocketmq.common.message.MessageExt;
import org.apache.rocketmq.common.message.MessageQueue;
import org.apache.rocketmq.common.protocol.ResponseCode;
import org.apache.rocketmq.common.protocol.header.EndTransactionRequestHeader;
import org.apache.rocketmq.common.sysflag.MessageSysFlag;
+import org.apache.rocketmq.common.topic.TopicValidator;
import org.apache.rocketmq.remoting.netty.NettyClientConfig;
import org.apache.rocketmq.remoting.netty.NettyServerConfig;
import org.apache.rocketmq.store.AppendMessageResult;
@@ -108,10 +108,10 @@ public class TransactionalMessageServiceImplTest {
@Test
public void testCheck_withDiscard() {
- when(bridge.fetchMessageQueues(MixAll.RMQ_SYS_TRANS_HALF_TOPIC)).thenReturn(createMessageQueueSet(MixAll.RMQ_SYS_TRANS_HALF_TOPIC));
- when(bridge.getHalfMessage(0, 0, 1)).thenReturn(createDiscardPullResult(MixAll.RMQ_SYS_TRANS_HALF_TOPIC, 5, "hellp", 1));
- when(bridge.getHalfMessage(0, 1, 1)).thenReturn(createPullResult(MixAll.RMQ_SYS_TRANS_HALF_TOPIC, 6, "hellp", 0));
- when(bridge.getOpMessage(anyInt(), anyLong(), anyInt())).thenReturn(createOpPulResult(MixAll.RMQ_SYS_TRANS_OP_HALF_TOPIC, 1, "10", 1));
+ when(bridge.fetchMessageQueues(TopicValidator.RMQ_SYS_TRANS_HALF_TOPIC)).thenReturn(createMessageQueueSet(TopicValidator.RMQ_SYS_TRANS_HALF_TOPIC));
+ when(bridge.getHalfMessage(0, 0, 1)).thenReturn(createDiscardPullResult(TopicValidator.RMQ_SYS_TRANS_HALF_TOPIC, 5, "hellp", 1));
+ when(bridge.getHalfMessage(0, 1, 1)).thenReturn(createPullResult(TopicValidator.RMQ_SYS_TRANS_HALF_TOPIC, 6, "hellp", 0));
+ when(bridge.getOpMessage(anyInt(), anyLong(), anyInt())).thenReturn(createOpPulResult(TopicValidator.RMQ_SYS_TRANS_OP_HALF_TOPIC, 1, "10", 1));
long timeOut = this.brokerController.getBrokerConfig().getTransactionTimeOut();
int checkMax = this.brokerController.getBrokerConfig().getTransactionCheckMax();
final AtomicInteger checkMessage = new AtomicInteger(0);
@@ -128,10 +128,10 @@ public class TransactionalMessageServiceImplTest {
@Test
public void testCheck_withCheck() {
- when(bridge.fetchMessageQueues(MixAll.RMQ_SYS_TRANS_HALF_TOPIC)).thenReturn(createMessageQueueSet(MixAll.RMQ_SYS_TRANS_HALF_TOPIC));
- when(bridge.getHalfMessage(0, 0, 1)).thenReturn(createPullResult(MixAll.RMQ_SYS_TRANS_HALF_TOPIC, 5, "hello", 1));
- when(bridge.getHalfMessage(0, 1, 1)).thenReturn(createPullResult(MixAll.RMQ_SYS_TRANS_HALF_TOPIC, 6, "hellp", 0));
- when(bridge.getOpMessage(anyInt(), anyLong(), anyInt())).thenReturn(createPullResult(MixAll.RMQ_SYS_TRANS_OP_HALF_TOPIC, 1, "5", 0));
+ when(bridge.fetchMessageQueues(TopicValidator.RMQ_SYS_TRANS_HALF_TOPIC)).thenReturn(createMessageQueueSet(TopicValidator.RMQ_SYS_TRANS_HALF_TOPIC));
+ when(bridge.getHalfMessage(0, 0, 1)).thenReturn(createPullResult(TopicValidator.RMQ_SYS_TRANS_HALF_TOPIC, 5, "hello", 1));
+ when(bridge.getHalfMessage(0, 1, 1)).thenReturn(createPullResult(TopicValidator.RMQ_SYS_TRANS_HALF_TOPIC, 6, "hellp", 0));
+ when(bridge.getOpMessage(anyInt(), anyLong(), anyInt())).thenReturn(createPullResult(TopicValidator.RMQ_SYS_TRANS_OP_HALF_TOPIC, 1, "5", 0));
when(bridge.getBrokerController()).thenReturn(this.brokerController);
when(bridge.renewHalfMessageInner(any(MessageExtBrokerInner.class))).thenReturn(createMessageBrokerInner());
when(bridge.putMessageReturnResult(any(MessageExtBrokerInner.class))).thenReturn(new PutMessageResult
diff --git a/client/pom.xml b/client/pom.xml
index b73b6b697b46cdff5288a104e46f17bcfa021873..95ef4617dd1b68b56cbebc6fab990ea783c8d602 100644
--- a/client/pom.xml
+++ b/client/pom.xml
@@ -19,7 +19,7 @@
org.apache.rocketmq
rocketmq-all
- 4.7.1-SNAPSHOT
+ 4.9.1-SNAPSHOT
4.0.0
@@ -27,11 +27,6 @@
rocketmq-client
rocketmq-client ${project.version}
-
- 1.6
- 1.6
-
-
${project.groupId}
@@ -52,6 +47,22 @@
org.apache.commons
commons-lang3
+
+ commons-codec
+ commons-codec
+
+
+ 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 d0ae5e1b8315370c3ce3373c330e9a7d0df2ca84..3ab214b8db6437f21ab13b0fb615bbaec89409e7 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/Validators.java b/client/src/main/java/org/apache/rocketmq/client/Validators.java
index d77faf3c222dbcc828c3182ceb4301ba25072d10..e712e2f5e46a2c34e9f21eea73790e0ec8d5d126 100644
--- a/client/src/main/java/org/apache/rocketmq/client/Validators.java
+++ b/client/src/main/java/org/apache/rocketmq/client/Validators.java
@@ -21,10 +21,10 @@ import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.rocketmq.client.exception.MQClientException;
import org.apache.rocketmq.client.producer.DefaultMQProducer;
-import org.apache.rocketmq.common.MixAll;
import org.apache.rocketmq.common.UtilAll;
import org.apache.rocketmq.common.message.Message;
import org.apache.rocketmq.common.protocol.ResponseCode;
+import org.apache.rocketmq.common.topic.TopicValidator;
/**
* Common Validator
@@ -85,6 +85,7 @@ public class Validators {
}
// topic
Validators.checkTopic(msg.getTopic());
+ Validators.isNotAllowedSendTopic(msg.getTopic());
// body
if (null == msg.getBody()) {
@@ -116,11 +117,19 @@ public class Validators {
throw new MQClientException(
String.format("The specified topic is longer than topic max length %d.", TOPIC_MAX_LENGTH), null);
}
+ }
+
+ public static void isSystemTopic(String topic) throws MQClientException {
+ if (TopicValidator.isSystemTopic(topic)) {
+ throw new MQClientException(
+ String.format("The topic[%s] is conflict with system topic.", topic), null);
+ }
+ }
- //whether the same with system reserved keyword
- if (topic.equals(MixAll.AUTO_CREATE_TOPIC_KEY_TOPIC)) {
+ public static void isNotAllowedSendTopic(String topic) throws MQClientException {
+ if (TopicValidator.isNotAllowedSendTopic(topic)) {
throw new MQClientException(
- String.format("The topic[%s] is conflict with AUTO_CREATE_TOPIC_KEY_TOPIC.", topic), null);
+ String.format("Sending message to topic[%s] is forbidden.", topic), null);
}
}
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 ab223c3ecac23c373716c4b2f5844c404328c892..891c17e3ba2c05a06816ada0502548ef32b4e9e2 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,21 +23,15 @@ 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;
+ this.threadLocalIndex.set(++index);
+ return Math.abs(index);
}
@Override
diff --git a/client/src/main/java/org/apache/rocketmq/client/consumer/DefaultLitePullConsumer.java b/client/src/main/java/org/apache/rocketmq/client/consumer/DefaultLitePullConsumer.java
index 6718eb55fd8730ac9ff0187f4f0b54fc48b932fa..c54399aa5ed24346fc801e4d9b15050ee7a2b997 100644
--- a/client/src/main/java/org/apache/rocketmq/client/consumer/DefaultLitePullConsumer.java
+++ b/client/src/main/java/org/apache/rocketmq/client/consumer/DefaultLitePullConsumer.java
@@ -23,6 +23,10 @@ import org.apache.rocketmq.client.consumer.rebalance.AllocateMessageQueueAverage
import org.apache.rocketmq.client.consumer.store.OffsetStore;
import org.apache.rocketmq.client.exception.MQClientException;
import org.apache.rocketmq.client.impl.consumer.DefaultLitePullConsumerImpl;
+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.ConsumeMessageTraceHookImpl;
import org.apache.rocketmq.common.MixAll;
import org.apache.rocketmq.common.UtilAll;
import org.apache.rocketmq.common.consumer.ConsumeFromWhere;
@@ -30,10 +34,13 @@ import org.apache.rocketmq.common.message.MessageExt;
import org.apache.rocketmq.common.message.MessageQueue;
import org.apache.rocketmq.common.protocol.NamespaceUtil;
import org.apache.rocketmq.common.protocol.heartbeat.MessageModel;
+import org.apache.rocketmq.logging.InternalLogger;
import org.apache.rocketmq.remoting.RPCHook;
public class DefaultLitePullConsumer extends ClientConfig implements LitePullConsumer {
+ private final InternalLogger log = ClientLogger.getLog();
+
private final DefaultLitePullConsumerImpl defaultLitePullConsumerImpl;
/**
@@ -153,6 +160,21 @@ public class DefaultLitePullConsumer extends ClientConfig implements LitePullCon
*/
private String consumeTimestamp = UtilAll.timeMillisToHumanString3(System.currentTimeMillis() - (1000 * 60 * 30));
+ /**
+ * Interface of asynchronous transfer data
+ */
+ private TraceDispatcher traceDispatcher = null;
+
+ /**
+ * The flag for message trace
+ */
+ private boolean enableMsgTrace = false;
+
+ /**
+ * The name value of message trace topic.If you don't config,you can use the default trace topic name.
+ */
+ private String customizedTraceTopic;
+
/**
* Default constructor.
*/
@@ -202,13 +224,29 @@ public class DefaultLitePullConsumer extends ClientConfig implements LitePullCon
@Override
public void start() throws MQClientException {
+ setTraceDispatcher();
setConsumerGroup(NamespaceUtil.wrapNamespace(this.getNamespace(), this.consumerGroup));
this.defaultLitePullConsumerImpl.start();
+ if (null != traceDispatcher) {
+ try {
+ traceDispatcher.start(this.getNamesrvAddr(), this.getAccessChannel());
+ } catch (MQClientException e) {
+ log.warn("trace dispatcher start failed ", e);
+ }
+ }
}
@Override
public void shutdown() {
this.defaultLitePullConsumerImpl.shutdown();
+ if (null != traceDispatcher) {
+ traceDispatcher.shutdown();
+ }
+ }
+
+ @Override
+ public boolean isRunning() {
+ return this.defaultLitePullConsumerImpl.isRunning();
}
@Override
@@ -307,6 +345,22 @@ public class DefaultLitePullConsumer extends ClientConfig implements LitePullCon
this.autoCommit = autoCommit;
}
+ public boolean isConnectBrokerByUser() {
+ return this.defaultLitePullConsumerImpl.getPullAPIWrapper().isConnectBrokerByUser();
+ }
+
+ public void setConnectBrokerByUser(boolean connectBrokerByUser) {
+ this.defaultLitePullConsumerImpl.getPullAPIWrapper().setConnectBrokerByUser(connectBrokerByUser);
+ }
+
+ public long getDefaultBrokerId() {
+ return this.defaultLitePullConsumerImpl.getPullAPIWrapper().getDefaultBrokerId();
+ }
+
+ public void setDefaultBrokerId(long defaultBrokerId) {
+ this.defaultLitePullConsumerImpl.getPullAPIWrapper().setDefaultBrokerId(defaultBrokerId);
+ }
+
public int getPullThreadNums() {
return pullThreadNums;
}
@@ -469,4 +523,36 @@ public class DefaultLitePullConsumer extends ClientConfig implements LitePullCon
public void setConsumeTimestamp(String consumeTimestamp) {
this.consumeTimestamp = consumeTimestamp;
}
+
+ public TraceDispatcher getTraceDispatcher() {
+ return traceDispatcher;
+ }
+
+ public void setCustomizedTraceTopic(String customizedTraceTopic) {
+ this.customizedTraceTopic = customizedTraceTopic;
+ }
+
+ private void setTraceDispatcher() {
+ if (isEnableMsgTrace()) {
+ try {
+ this.traceDispatcher = new AsyncTraceDispatcher(consumerGroup, TraceDispatcher.Type.CONSUME, customizedTraceTopic, null);
+ this.defaultLitePullConsumerImpl.registerConsumeMessageHook(
+ new ConsumeMessageTraceHookImpl(traceDispatcher));
+ } catch (Throwable e) {
+ log.error("system mqtrace hook init failed ,maybe can't send msg trace data");
+ }
+ }
+ }
+
+ public String getCustomizedTraceTopic() {
+ return customizedTraceTopic;
+ }
+
+ public boolean isEnableMsgTrace() {
+ return enableMsgTrace;
+ }
+
+ public void setEnableMsgTrace(boolean enableMsgTrace) {
+ this.enableMsgTrace = enableMsgTrace;
+ }
}
diff --git a/client/src/main/java/org/apache/rocketmq/client/consumer/DefaultMQPushConsumer.java b/client/src/main/java/org/apache/rocketmq/client/consumer/DefaultMQPushConsumer.java
index 6ad0fc308ecfbf11951a4f56ac778c1f58a289ec..9011117a79fc247800c3c9aa06d58c5c97bb01a8 100644
--- a/client/src/main/java/org/apache/rocketmq/client/consumer/DefaultMQPushConsumer.java
+++ b/client/src/main/java/org/apache/rocketmq/client/consumer/DefaultMQPushConsumer.java
@@ -254,6 +254,11 @@ public class DefaultMQPushConsumer extends ClientConfig implements MQPushConsume
*/
private long consumeTimeout = 15;
+ /**
+ * Maximum time to await message consuming when shutdown consumer, 0 indicates no await.
+ */
+ private long awaitTerminationMillisWhenShutdown = 0;
+
/**
* Interface of asynchronous transfer data
*/
@@ -705,7 +710,7 @@ public class DefaultMQPushConsumer extends ClientConfig implements MQPushConsume
*/
@Override
public void shutdown() {
- this.defaultMQPushConsumerImpl.shutdown();
+ this.defaultMQPushConsumerImpl.shutdown(awaitTerminationMillisWhenShutdown);
if (null != traceDispatcher) {
traceDispatcher.shutdown();
}
@@ -886,6 +891,14 @@ public class DefaultMQPushConsumer extends ClientConfig implements MQPushConsume
this.consumeTimeout = consumeTimeout;
}
+ public long getAwaitTerminationMillisWhenShutdown() {
+ return awaitTerminationMillisWhenShutdown;
+ }
+
+ public void setAwaitTerminationMillisWhenShutdown(long awaitTerminationMillisWhenShutdown) {
+ this.awaitTerminationMillisWhenShutdown = awaitTerminationMillisWhenShutdown;
+ }
+
public TraceDispatcher getTraceDispatcher() {
return traceDispatcher;
}
diff --git a/client/src/main/java/org/apache/rocketmq/client/consumer/LitePullConsumer.java b/client/src/main/java/org/apache/rocketmq/client/consumer/LitePullConsumer.java
index ce2228803383d7fc1502b0fa5babd9bd1ec5c0ac..25b11046f84d7e98ecadd1b7cf8af6ae80625107 100644
--- a/client/src/main/java/org/apache/rocketmq/client/consumer/LitePullConsumer.java
+++ b/client/src/main/java/org/apache/rocketmq/client/consumer/LitePullConsumer.java
@@ -35,6 +35,13 @@ public interface LitePullConsumer {
*/
void shutdown();
+ /**
+ * This consumer is still running
+ *
+ * @return true if consumer is still running
+ */
+ boolean isRunning();
+
/**
* Subscribe some topic with subExpression
*
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 37568317cb016638ef5d56c23341051810ce8ec9..31f4e3522ec6e2a769f427f27118d5d616ca33a9 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/exception/MQBrokerException.java b/client/src/main/java/org/apache/rocketmq/client/exception/MQBrokerException.java
index e4f2c8df85022b66f6345cd7c28edff8af44d6aa..f07a38b81f0a3689015eed3ac63f6f2fb12cb457 100644
--- a/client/src/main/java/org/apache/rocketmq/client/exception/MQBrokerException.java
+++ b/client/src/main/java/org/apache/rocketmq/client/exception/MQBrokerException.java
@@ -23,12 +23,22 @@ public class MQBrokerException extends Exception {
private static final long serialVersionUID = 5975020272601250368L;
private final int responseCode;
private final String errorMessage;
+ private final String brokerAddr;
public MQBrokerException(int responseCode, String errorMessage) {
super(FAQUrl.attachDefaultURL("CODE: " + UtilAll.responseCode2String(responseCode) + " DESC: "
- + errorMessage));
+ + errorMessage));
this.responseCode = responseCode;
this.errorMessage = errorMessage;
+ this.brokerAddr = null;
+ }
+
+ public MQBrokerException(int responseCode, String errorMessage, String brokerAddr) {
+ super(FAQUrl.attachDefaultURL("CODE: " + UtilAll.responseCode2String(responseCode) + " DESC: "
+ + errorMessage + (brokerAddr != null ? " BROKER: " + brokerAddr : "")));
+ this.responseCode = responseCode;
+ this.errorMessage = errorMessage;
+ this.brokerAddr = brokerAddr;
}
public int getResponseCode() {
@@ -38,4 +48,8 @@ public class MQBrokerException extends Exception {
public String getErrorMessage() {
return errorMessage;
}
+
+ public String getBrokerAddr() {
+ return brokerAddr;
+ }
}
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 0000000000000000000000000000000000000000..5271ade82bff79cacb6c5d9e822003c80cfaf503
--- /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 0000000000000000000000000000000000000000..834cb2731264b150e6ad52f6c5be74ba5e6087c3
--- /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 3ef60af1799a9c91664581f8b596bb4046c6da1b..a541b2d379c6d6eea857240978e759801543fb99 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/MQAdminImpl.java b/client/src/main/java/org/apache/rocketmq/client/impl/MQAdminImpl.java
index 9dbd55201dc6bea8ff1046e59be1fbd674a2b63b..8884e4adfef9efd5caef99845d9e1ba4cd7c4da1 100644
--- a/client/src/main/java/org/apache/rocketmq/client/impl/MQAdminImpl.java
+++ b/client/src/main/java/org/apache/rocketmq/client/impl/MQAdminImpl.java
@@ -82,6 +82,7 @@ public class MQAdminImpl {
public void createTopic(String key, String newTopic, int queueNum, int topicSysFlag) throws MQClientException {
try {
Validators.checkTopic(newTopic);
+ Validators.isSystemTopic(newTopic);
TopicRouteData topicRouteData = this.mQClientFactory.getMQClientAPIImpl().getTopicRouteInfoFromNameServer(key, timeoutMillis);
List brokerDataList = topicRouteData.getBrokerDatas();
if (brokerDataList != null && !brokerDataList.isEmpty()) {
@@ -267,17 +268,23 @@ public class MQAdminImpl {
messageId.getOffset(), timeoutMillis);
}
- public QueryResult queryMessage(String topic, String key, int maxNum, long begin,
- long end) throws MQClientException,
- InterruptedException {
+ public QueryResult queryMessage(String topic, String key, int maxNum, long begin, long end)
+ throws MQClientException, InterruptedException {
+
return queryMessage(topic, key, maxNum, begin, end, false);
}
+ public QueryResult queryMessageByUniqKey(String topic, String uniqKey, int maxNum, long begin, long end)
+ throws MQClientException, InterruptedException {
+
+ return queryMessage(topic, uniqKey, maxNum, begin, end, true);
+ }
+
public MessageExt queryMessageByUniqKey(String topic,
String uniqKey) throws InterruptedException, MQClientException {
- QueryResult qr = this.queryMessage(topic, uniqKey, 32,
- MessageClientIDSetter.getNearlyTimeFromID(uniqKey).getTime() - 1000, Long.MAX_VALUE, true);
+ QueryResult qr = queryMessageByUniqKey(topic, uniqKey, 32,
+ MessageClientIDSetter.getNearlyTimeFromID(uniqKey).getTime() - 1000, Long.MAX_VALUE);
if (qr != null && qr.getMessageList() != null && qr.getMessageList().size() > 0) {
return qr.getMessageList().get(0);
} else {
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 073e3679be0462ed657a942c1a63ba0698f04931..63b2045d1d5d5665217ac80c106cd703205c53eb 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
@@ -390,7 +390,7 @@ public class MQClientAPIImpl {
break;
}
- throw new MQBrokerException(response.getCode(), response.getRemark());
+ throw new MQBrokerException(response.getCode(), response.getRemark(), addr);
}
@@ -414,7 +414,7 @@ public class MQClientAPIImpl {
default:
break;
}
- throw new MQBrokerException(response.getCode(), response.getRemark());
+ throw new MQBrokerException(response.getCode(), response.getRemark(), addr);
}
@@ -502,7 +502,7 @@ public class MQClientAPIImpl {
) throws RemotingException, MQBrokerException, InterruptedException {
RemotingCommand response = this.remotingClient.invokeSync(addr, request, timeoutMillis);
assert response != null;
- return this.processSendResponse(brokerName, msg, response);
+ return this.processSendResponse(brokerName, msg, response,addr);
}
private void sendMessageAsync(
@@ -528,7 +528,7 @@ public class MQClientAPIImpl {
if (null == sendCallback && response != null) {
try {
- SendResult sendResult = MQClientAPIImpl.this.processSendResponse(brokerName, msg, response);
+ SendResult sendResult = MQClientAPIImpl.this.processSendResponse(brokerName, msg, response, addr);
if (context != null && sendResult != null) {
context.setSendResult(sendResult);
context.getProducer().executeSendMessageHookAfter(context);
@@ -542,7 +542,7 @@ public class MQClientAPIImpl {
if (response != null) {
try {
- SendResult sendResult = MQClientAPIImpl.this.processSendResponse(brokerName, msg, response);
+ SendResult sendResult = MQClientAPIImpl.this.processSendResponse(brokerName, msg, response, addr);
assert sendResult != null;
if (context != null) {
context.setSendResult(sendResult);
@@ -641,7 +641,8 @@ public class MQClientAPIImpl {
private SendResult processSendResponse(
final String brokerName,
final Message msg,
- final RemotingCommand response
+ final RemotingCommand response,
+ final String addr
) throws MQBrokerException, RemotingCommandException {
SendStatus sendStatus;
switch (response.getCode()) {
@@ -662,7 +663,7 @@ public class MQClientAPIImpl {
break;
}
default: {
- throw new MQBrokerException(response.getCode(), response.getRemark());
+ throw new MQBrokerException(response.getCode(), response.getRemark(), addr);
}
}
@@ -741,7 +742,7 @@ public class MQClientAPIImpl {
RemotingCommand response = responseFuture.getResponseCommand();
if (response != null) {
try {
- PullResult pullResult = MQClientAPIImpl.this.processPullResponse(response);
+ PullResult pullResult = MQClientAPIImpl.this.processPullResponse(response, addr);
assert pullResult != null;
pullCallback.onSuccess(pullResult);
} catch (Exception e) {
@@ -768,11 +769,12 @@ public class MQClientAPIImpl {
) throws RemotingException, InterruptedException, MQBrokerException {
RemotingCommand response = this.remotingClient.invokeSync(addr, request, timeoutMillis);
assert response != null;
- return this.processPullResponse(response);
+ return this.processPullResponse(response, addr);
}
private PullResult processPullResponse(
- final RemotingCommand response) throws MQBrokerException, RemotingCommandException {
+ final RemotingCommand response,
+ final String addr) throws MQBrokerException, RemotingCommandException {
PullStatus pullStatus = PullStatus.NO_NEW_MSG;
switch (response.getCode()) {
case ResponseCode.SUCCESS:
@@ -789,7 +791,7 @@ public class MQClientAPIImpl {
break;
default:
- throw new MQBrokerException(response.getCode(), response.getRemark());
+ throw new MQBrokerException(response.getCode(), response.getRemark(), addr);
}
PullMessageResponseHeader responseHeader =
@@ -822,7 +824,7 @@ public class MQClientAPIImpl {
break;
}
- throw new MQBrokerException(response.getCode(), response.getRemark());
+ throw new MQBrokerException(response.getCode(), response.getRemark(), addr);
}
public long searchOffset(final String addr, final String topic, final int queueId, final long timestamp,
@@ -847,7 +849,7 @@ public class MQClientAPIImpl {
break;
}
- throw new MQBrokerException(response.getCode(), response.getRemark());
+ throw new MQBrokerException(response.getCode(), response.getRemark(), addr);
}
public long getMaxOffset(final String addr, final String topic, final int queueId, final long timeoutMillis)
@@ -871,7 +873,7 @@ public class MQClientAPIImpl {
break;
}
- throw new MQBrokerException(response.getCode(), response.getRemark());
+ throw new MQBrokerException(response.getCode(), response.getRemark(), addr);
}
public List getConsumerIdListByGroup(
@@ -898,7 +900,7 @@ public class MQClientAPIImpl {
break;
}
- throw new MQBrokerException(response.getCode(), response.getRemark());
+ throw new MQBrokerException(response.getCode(), response.getRemark(), addr);
}
public long getMinOffset(final String addr, final String topic, final int queueId, final long timeoutMillis)
@@ -922,7 +924,7 @@ public class MQClientAPIImpl {
break;
}
- throw new MQBrokerException(response.getCode(), response.getRemark());
+ throw new MQBrokerException(response.getCode(), response.getRemark(), addr);
}
public long getEarliestMsgStoretime(final String addr, final String topic, final int queueId,
@@ -947,7 +949,7 @@ public class MQClientAPIImpl {
break;
}
- throw new MQBrokerException(response.getCode(), response.getRemark());
+ throw new MQBrokerException(response.getCode(), response.getRemark(), addr);
}
public long queryConsumerOffset(
@@ -971,7 +973,7 @@ public class MQClientAPIImpl {
break;
}
- throw new MQBrokerException(response.getCode(), response.getRemark());
+ throw new MQBrokerException(response.getCode(), response.getRemark(), addr);
}
public void updateConsumerOffset(
@@ -992,7 +994,7 @@ public class MQClientAPIImpl {
break;
}
- throw new MQBrokerException(response.getCode(), response.getRemark());
+ throw new MQBrokerException(response.getCode(), response.getRemark(), addr);
}
public void updateConsumerOffsetOneway(
@@ -1024,7 +1026,7 @@ public class MQClientAPIImpl {
break;
}
- throw new MQBrokerException(response.getCode(), response.getRemark());
+ throw new MQBrokerException(response.getCode(), response.getRemark(), addr);
}
public void unregisterClient(
@@ -1050,7 +1052,7 @@ public class MQClientAPIImpl {
break;
}
- throw new MQBrokerException(response.getCode(), response.getRemark());
+ throw new MQBrokerException(response.getCode(), response.getRemark(), addr);
}
public void endTransactionOneway(
@@ -1116,7 +1118,7 @@ public class MQClientAPIImpl {
break;
}
- throw new MQBrokerException(response.getCode(), response.getRemark());
+ throw new MQBrokerException(response.getCode(), response.getRemark(), addr);
}
public Set lockBatchMQ(
@@ -1138,7 +1140,7 @@ public class MQClientAPIImpl {
break;
}
- throw new MQBrokerException(response.getCode(), response.getRemark());
+ throw new MQBrokerException(response.getCode(), response.getRemark(), addr);
}
public void unlockBatchMQ(
@@ -1164,7 +1166,7 @@ public class MQClientAPIImpl {
break;
}
- throw new MQBrokerException(response.getCode(), response.getRemark());
+ throw new MQBrokerException(response.getCode(), response.getRemark(), addr);
}
}
@@ -1187,7 +1189,7 @@ public class MQClientAPIImpl {
break;
}
- throw new MQBrokerException(response.getCode(), response.getRemark());
+ throw new MQBrokerException(response.getCode(), response.getRemark(), addr);
}
public ConsumeStats getConsumeStats(final String addr, final String consumerGroup, final long timeoutMillis)
@@ -1217,7 +1219,7 @@ public class MQClientAPIImpl {
break;
}
- throw new MQBrokerException(response.getCode(), response.getRemark());
+ throw new MQBrokerException(response.getCode(), response.getRemark(), addr);
}
public ProducerConnection getProducerConnectionList(final String addr, final String producerGroup,
@@ -1239,7 +1241,7 @@ public class MQClientAPIImpl {
break;
}
- throw new MQBrokerException(response.getCode(), response.getRemark());
+ throw new MQBrokerException(response.getCode(), response.getRemark(), addr);
}
public ConsumerConnection getConsumerConnectionList(final String addr, final String consumerGroup,
@@ -1261,7 +1263,7 @@ public class MQClientAPIImpl {
break;
}
- throw new MQBrokerException(response.getCode(), response.getRemark());
+ throw new MQBrokerException(response.getCode(), response.getRemark(), addr);
}
public KVTable getBrokerRuntimeInfo(final String addr, final long timeoutMillis) throws RemotingConnectException,
@@ -1279,7 +1281,7 @@ public class MQClientAPIImpl {
break;
}
- throw new MQBrokerException(response.getCode(), response.getRemark());
+ throw new MQBrokerException(response.getCode(), response.getRemark(), addr);
}
public void updateBrokerConfig(final String addr, final Properties properties, final long timeoutMillis)
@@ -1301,7 +1303,7 @@ public class MQClientAPIImpl {
break;
}
- throw new MQBrokerException(response.getCode(), response.getRemark());
+ throw new MQBrokerException(response.getCode(), response.getRemark(), addr);
}
}
@@ -1320,7 +1322,7 @@ public class MQClientAPIImpl {
break;
}
- throw new MQBrokerException(response.getCode(), response.getRemark());
+ throw new MQBrokerException(response.getCode(), response.getRemark(), addr);
}
public ClusterInfo getBrokerClusterInfo(
@@ -1364,7 +1366,7 @@ public class MQClientAPIImpl {
assert response != null;
switch (response.getCode()) {
case ResponseCode.TOPIC_NOT_EXIST: {
- if (allowTopicNotExist && !topic.equals(MixAll.AUTO_CREATE_TOPIC_KEY_TOPIC)) {
+ if (allowTopicNotExist) {
log.warn("get Topic [{}] RouteInfoFromNameServer is not exist value", topic);
}
@@ -1465,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),
@@ -1670,7 +1673,7 @@ public class MQClientAPIImpl {
break;
}
- throw new MQBrokerException(response.getCode(), response.getRemark());
+ throw new MQBrokerException(response.getCode(), response.getRemark(), addr);
}
public List queryConsumeTimeSpan(final String addr, final String topic, final String group,
@@ -1694,7 +1697,7 @@ public class MQClientAPIImpl {
break;
}
- throw new MQBrokerException(response.getCode(), response.getRemark());
+ throw new MQBrokerException(response.getCode(), response.getRemark(), addr);
}
public TopicList getTopicsByCluster(final String cluster, final long timeoutMillis)
@@ -1745,7 +1748,7 @@ public class MQClientAPIImpl {
break;
}
- throw new MQBrokerException(response.getCode(), response.getRemark());
+ throw new MQBrokerException(response.getCode(), response.getRemark(), addr);
}
public TopicList getSystemTopicList(
@@ -2108,7 +2111,7 @@ public class MQClientAPIImpl {
default:
break;
}
- throw new MQBrokerException(response.getCode(), response.getRemark());
+ throw new MQBrokerException(response.getCode(), response.getRemark(), brokerAddr);
}
public TopicConfigSerializeWrapper getAllTopicConfig(final String addr,
@@ -2127,7 +2130,7 @@ public class MQClientAPIImpl {
break;
}
- throw new MQBrokerException(response.getCode(), response.getRemark());
+ throw new MQBrokerException(response.getCode(), response.getRemark(), addr);
}
public void updateNameServerConfig(final Properties properties, final List nameServers, long timeoutMillis)
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 fad0b4f1b584d301c7683aac3be36531627e2721..4d18a9be1b7c7fbdb870fef98a9d45075879c142 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/ConsumeMessageConcurrentlyService.java b/client/src/main/java/org/apache/rocketmq/client/impl/consumer/ConsumeMessageConcurrentlyService.java
index 258e4dbf8777fd6c5d1f0aa0cb947da332c6064f..b37f8a635983573c28d42a6708e0ed1ffee91b92 100644
--- a/client/src/main/java/org/apache/rocketmq/client/impl/consumer/ConsumeMessageConcurrentlyService.java
+++ b/client/src/main/java/org/apache/rocketmq/client/impl/consumer/ConsumeMessageConcurrentlyService.java
@@ -45,6 +45,7 @@ import org.apache.rocketmq.common.message.MessageExt;
import org.apache.rocketmq.common.message.MessageQueue;
import org.apache.rocketmq.common.protocol.body.CMResult;
import org.apache.rocketmq.common.protocol.body.ConsumeMessageDirectlyResult;
+import org.apache.rocketmq.common.utils.ThreadUtils;
import org.apache.rocketmq.logging.InternalLogger;
import org.apache.rocketmq.remoting.common.RemotingHelper;
@@ -92,9 +93,9 @@ public class ConsumeMessageConcurrentlyService implements ConsumeMessageService
}, this.defaultMQPushConsumer.getConsumeTimeout(), this.defaultMQPushConsumer.getConsumeTimeout(), TimeUnit.MINUTES);
}
- public void shutdown() {
+ public void shutdown(long awaitTerminateMillis) {
this.scheduledExecutorService.shutdown();
- this.consumeExecutor.shutdown();
+ ThreadUtils.shutdownGracefully(this.consumeExecutor, awaitTerminateMillis, TimeUnit.MILLISECONDS);
this.cleanExpireMsgExecutors.shutdown();
}
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 f65567b685d723a5b65b465f0a93c363c985d450..130effad9e55f08ede275f6870ba9976f11f5f56 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
@@ -40,6 +40,7 @@ import org.apache.rocketmq.common.MixAll;
import org.apache.rocketmq.common.ThreadFactoryImpl;
import org.apache.rocketmq.common.UtilAll;
import org.apache.rocketmq.common.protocol.NamespaceUtil;
+import org.apache.rocketmq.common.utils.ThreadUtils;
import org.apache.rocketmq.logging.InternalLogger;
import org.apache.rocketmq.common.message.Message;
import org.apache.rocketmq.common.message.MessageAccessor;
@@ -96,10 +97,10 @@ public class ConsumeMessageOrderlyService implements ConsumeMessageService {
}
}
- public void shutdown() {
+ public void shutdown(long awaitTerminateMillis) {
this.stopped = true;
this.scheduledExecutorService.shutdown();
- this.consumeExecutor.shutdown();
+ ThreadUtils.shutdownGracefully(this.consumeExecutor, awaitTerminateMillis, TimeUnit.MILLISECONDS);
if (MessageModel.CLUSTERING.equals(this.defaultMQPushConsumerImpl.messageModel())) {
this.unlockAllMQ();
}
@@ -279,7 +280,7 @@ public class ConsumeMessageOrderlyService implements ConsumeMessageService {
case SUSPEND_CURRENT_QUEUE_A_MOMENT:
this.getConsumerStatsManager().incConsumeFailedTPS(consumerGroup, consumeRequest.getMessageQueue().getTopic(), msgs.size());
if (checkReconsumeTimes(msgs)) {
- consumeRequest.getProcessQueue().makeMessageToCosumeAgain(msgs);
+ consumeRequest.getProcessQueue().makeMessageToConsumeAgain(msgs);
this.submitConsumeRequestLater(
consumeRequest.getProcessQueue(),
consumeRequest.getMessageQueue(),
@@ -311,7 +312,7 @@ public class ConsumeMessageOrderlyService implements ConsumeMessageService {
case SUSPEND_CURRENT_QUEUE_A_MOMENT:
this.getConsumerStatsManager().incConsumeFailedTPS(consumerGroup, consumeRequest.getMessageQueue().getTopic(), msgs.size());
if (checkReconsumeTimes(msgs)) {
- consumeRequest.getProcessQueue().makeMessageToCosumeAgain(msgs);
+ consumeRequest.getProcessQueue().makeMessageToConsumeAgain(msgs);
this.submitConsumeRequestLater(
consumeRequest.getProcessQueue(),
consumeRequest.getMessageQueue(),
@@ -477,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);
@@ -493,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/ConsumeMessageService.java b/client/src/main/java/org/apache/rocketmq/client/impl/consumer/ConsumeMessageService.java
index 0f6f3bb38af6d22e02044bdaa738d2a8d45c2e8c..5078c97883502f198d1d2f395b42b0f4ee6262bb 100644
--- a/client/src/main/java/org/apache/rocketmq/client/impl/consumer/ConsumeMessageService.java
+++ b/client/src/main/java/org/apache/rocketmq/client/impl/consumer/ConsumeMessageService.java
@@ -24,7 +24,7 @@ import org.apache.rocketmq.common.protocol.body.ConsumeMessageDirectlyResult;
public interface ConsumeMessageService {
void start();
- void shutdown();
+ void shutdown(long awaitTerminateMillis);
void updateCorePoolSize(int corePoolSize);
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 f54078fcfdc687a650444e147d5cbb59779b6fe9..4e139c44ce0c25d0eee8b01bc2f87804a036c8b9 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
@@ -41,12 +41,15 @@ import org.apache.rocketmq.client.consumer.MessageQueueListener;
import org.apache.rocketmq.client.consumer.MessageSelector;
import org.apache.rocketmq.client.consumer.PullResult;
import org.apache.rocketmq.client.consumer.TopicMessageQueueChangeListener;
+import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus;
import org.apache.rocketmq.client.consumer.store.LocalFileOffsetStore;
import org.apache.rocketmq.client.consumer.store.OffsetStore;
import org.apache.rocketmq.client.consumer.store.ReadOffsetType;
import org.apache.rocketmq.client.consumer.store.RemoteBrokerOffsetStore;
import org.apache.rocketmq.client.exception.MQBrokerException;
import org.apache.rocketmq.client.exception.MQClientException;
+import org.apache.rocketmq.client.hook.ConsumeMessageContext;
+import org.apache.rocketmq.client.hook.ConsumeMessageHook;
import org.apache.rocketmq.client.hook.FilterMessageHook;
import org.apache.rocketmq.client.impl.CommunicationMode;
import org.apache.rocketmq.client.impl.MQClientManager;
@@ -115,6 +118,8 @@ public class DefaultLitePullConsumerImpl implements MQConsumerInner {
*/
private static final long PULL_TIME_DELAY_MILLS_WHEN_PAUSE = 1000;
+ private static final long PULL_TIME_DELAY_MILLS_ON_EXCEPTION = 3 * 1000;
+
private DefaultLitePullConsumer defaultLitePullConsumer;
private final ConcurrentMap taskTable =
@@ -142,6 +147,8 @@ public class DefaultLitePullConsumerImpl implements MQConsumerInner {
private final MessageQueueLock messageQueueLock = new MessageQueueLock();
+ private final ArrayList consumeMessageHookList = new ArrayList<>();
+
public DefaultLitePullConsumerImpl(final DefaultLitePullConsumer defaultLitePullConsumer, final RPCHook rpcHook) {
this.defaultLitePullConsumer = defaultLitePullConsumer;
this.rpcHook = rpcHook;
@@ -158,6 +165,35 @@ public class DefaultLitePullConsumerImpl implements MQConsumerInner {
this.pullTimeDelayMillsWhenException = defaultLitePullConsumer.getPullTimeDelayMillsWhenException();
}
+ public void registerConsumeMessageHook(final ConsumeMessageHook hook) {
+ this.consumeMessageHookList.add(hook);
+ log.info("register consumeMessageHook Hook, {}", hook.hookName());
+ }
+
+ public void executeHookBefore(final ConsumeMessageContext context) {
+ if (!this.consumeMessageHookList.isEmpty()) {
+ for (ConsumeMessageHook hook : this.consumeMessageHookList) {
+ try {
+ hook.consumeMessageBefore(context);
+ } catch (Throwable e) {
+ log.error("consumeMessageHook {} executeHookBefore exception", hook.hookName(), e);
+ }
+ }
+ }
+ }
+
+ public void executeHookAfter(final ConsumeMessageContext context) {
+ if (!this.consumeMessageHookList.isEmpty()) {
+ for (ConsumeMessageHook hook : this.consumeMessageHookList) {
+ try {
+ hook.consumeMessageAfter(context);
+ } catch (Throwable e) {
+ log.error("consumeMessageHook {} executeHookAfter exception", hook.hookName(), e);
+ }
+ }
+ }
+ }
+
private void checkServiceState() {
if (this.serviceState != ServiceState.RUNNING)
throw new IllegalStateException(NOT_RUNNING_EXCEPTION_MESSAGE);
@@ -229,6 +265,10 @@ public class DefaultLitePullConsumerImpl implements MQConsumerInner {
}
}
+ public synchronized boolean isRunning() {
+ return this.serviceState == ServiceState.RUNNING;
+ }
+
public synchronized void start() throws MQClientException {
switch (this.serviceState) {
case CREATE_JUST:
@@ -428,8 +468,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);
@@ -609,9 +648,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);
}
}
@@ -623,9 +662,9 @@ public class DefaultLitePullConsumerImpl implements MQConsumerInner {
}
}
- private long fetchConsumeOffset(MessageQueue messageQueue) {
+ private long fetchConsumeOffset(MessageQueue messageQueue) throws MQClientException {
checkServiceState();
- long offset = this.rebalanceImpl.computePullFromWhere(messageQueue);
+ long offset = this.rebalanceImpl.computePullFromWhereWithException(messageQueue);
return offset;
}
@@ -649,7 +688,7 @@ public class DefaultLitePullConsumerImpl implements MQConsumerInner {
}
}
- private long nextPullOffset(MessageQueue messageQueue) {
+ private long nextPullOffset(MessageQueue messageQueue) throws MQClientException {
long offset = -1;
long seekOffset = assignedMessageQueue.getSeekOffset(messageQueue);
if (seekOffset != -1) {
@@ -691,7 +730,7 @@ public class DefaultLitePullConsumerImpl implements MQConsumerInner {
ProcessQueue processQueue = assignedMessageQueue.getProcessQueue(messageQueue);
- if (processQueue == null && processQueue.isDropped()) {
+ if (null == processQueue || processQueue.isDropped()) {
log.info("The message queue not be able to poll, because it's dropped. group={}, messageQueue={}", defaultLitePullConsumer.getConsumerGroup(), this.messageQueue);
return;
}
@@ -736,7 +775,18 @@ public class DefaultLitePullConsumerImpl implements MQConsumerInner {
return;
}
- long offset = nextPullOffset(messageQueue);
+ long offset = 0L;
+ try {
+ offset = nextPullOffset(messageQueue);
+ } catch (MQClientException e) {
+ log.error("Failed to get next pull offset", e);
+ scheduledThreadPoolExecutor.schedule(this, PULL_TIME_DELAY_MILLS_ON_EXCEPTION, TimeUnit.MILLISECONDS);
+ return;
+ }
+
+ if (this.isCancelled() || processQueue.isDropped()) {
+ return;
+ }
long pullDelayTimeMills = 0;
try {
SubscriptionData subscriptionData;
@@ -745,12 +795,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);
@@ -767,7 +818,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);
@@ -841,6 +892,18 @@ public class DefaultLitePullConsumerImpl implements MQConsumerInner {
null
);
this.pullAPIWrapper.processPullResult(mq, pullResult, subscriptionData);
+ if (!this.consumeMessageHookList.isEmpty()) {
+ ConsumeMessageContext consumeMessageContext = new ConsumeMessageContext();
+ consumeMessageContext.setNamespace(defaultLitePullConsumer.getNamespace());
+ consumeMessageContext.setConsumerGroup(this.groupName());
+ consumeMessageContext.setMq(mq);
+ consumeMessageContext.setMsgList(pullResult.getMsgFoundList());
+ consumeMessageContext.setSuccess(false);
+ this.executeHookBefore(consumeMessageContext);
+ consumeMessageContext.setStatus(ConsumeConcurrentlyStatus.CONSUME_SUCCESS.toString());
+ consumeMessageContext.setSuccess(true);
+ this.executeHookAfter(consumeMessageContext);
+ }
return pullResult;
}
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 afd72a08002c6c9124feb6260f011e9810407842..eed5fa43f04fff819345def276320a442ee3f9fc 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 25a81a0e755e60e968ae281d4390cff5b77edcc7..bb0b7f10436ad7ef0844bad9ec09849c72b5940c 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
@@ -269,8 +269,15 @@ public class DefaultMQPushConsumerImpl implements MQConsumerInner {
}
} else {
if (processQueue.isLocked()) {
- if (!pullRequest.isLockedFirst()) {
- final long offset = this.rebalanceImpl.computePullFromWhere(pullRequest.getMessageQueue());
+ if (!pullRequest.isPreviouslyLocked()) {
+ long offset = -1L;
+ try {
+ offset = this.rebalanceImpl.computePullFromWhereWithException(pullRequest.getMessageQueue());
+ } catch (MQClientException e) {
+ this.executePullRequestLater(pullRequest, pullTimeDelayMillsWhenException);
+ log.error("Failed to compute pull offset, pullResult: {}", pullRequest, e);
+ return;
+ }
boolean brokerBusy = offset < pullRequest.getNextOffset();
log.info("the first time to pull message, so fix offset from broker. pullRequest: {} NewOffset: {} brokerBusy: {}",
pullRequest, offset, brokerBusy);
@@ -279,7 +286,7 @@ public class DefaultMQPushConsumerImpl implements MQConsumerInner {
pullRequest, offset);
}
- pullRequest.setLockedFirst(true);
+ pullRequest.setPreviouslyLocked(true);
pullRequest.setNextOffset(offset);
}
} else {
@@ -348,12 +355,6 @@ public class DefaultMQPushConsumerImpl implements MQConsumerInner {
break;
case NO_NEW_MSG:
- pullRequest.setNextOffset(pullResult.getNextBeginOffset());
-
- DefaultMQPushConsumerImpl.this.correctTagsOffset(pullRequest);
-
- DefaultMQPushConsumerImpl.this.executePullRequestImmediately(pullRequest);
- break;
case NO_MATCHED_MSG:
pullRequest.setNextOffset(pullResult.getNextBeginOffset());
@@ -546,12 +547,16 @@ public class DefaultMQPushConsumerImpl implements MQConsumerInner {
}
}
- public synchronized void shutdown() {
+ public void shutdown() {
+ shutdown(0);
+ }
+
+ public synchronized void shutdown(long awaitTerminateMillis) {
switch (this.serviceState) {
case CREATE_JUST:
break;
case RUNNING:
- this.consumeMessageService.shutdown();
+ this.consumeMessageService.shutdown(awaitTerminateMillis);
this.persistConsumerOffset();
this.mQClientFactory.unregisterConsumer(this.defaultMQPushConsumer.getConsumerGroup());
this.mQClientFactory.shutdown();
@@ -625,7 +630,7 @@ public class DefaultMQPushConsumerImpl implements MQConsumerInner {
boolean registerOK = mQClientFactory.registerConsumer(this.defaultMQPushConsumer.getConsumerGroup(), this);
if (!registerOK) {
this.serviceState = ServiceState.CREATE_JUST;
- this.consumeMessageService.shutdown();
+ this.consumeMessageService.shutdown(defaultMQPushConsumer.getAwaitTerminationMillisWhenShutdown());
throw new MQClientException("The consumer group[" + this.defaultMQPushConsumer.getConsumerGroup()
+ "] has been created before, specify another name please." + FAQUrl.suggestTodo(FAQUrl.GROUP_NAME_DUPLICATE_URL),
null);
@@ -829,8 +834,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);
}
}
@@ -844,8 +848,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:
@@ -876,8 +879,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();
@@ -889,8 +891,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 f659bd3f83100c5a1837f4ecadc7bbfdee9f63aa..21798d8c6ec03d6bb82d5cf32b5c84327be4dc42 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);
@@ -280,16 +280,16 @@ public class ProcessQueue {
return -1;
}
- public void makeMessageToCosumeAgain(List msgs) {
+ 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/PullAPIWrapper.java b/client/src/main/java/org/apache/rocketmq/client/impl/consumer/PullAPIWrapper.java
index 231ac0c68f3e26d099de8318c62741d320e7cb57..cc42a9e830ee9dde11869423dd879cefdd9d967a 100644
--- a/client/src/main/java/org/apache/rocketmq/client/impl/consumer/PullAPIWrapper.java
+++ b/client/src/main/java/org/apache/rocketmq/client/impl/consumer/PullAPIWrapper.java
@@ -194,7 +194,7 @@ public class PullAPIWrapper {
String brokerAddr = findBrokerResult.getBrokerAddr();
if (PullSysFlag.hasClassFilterFlag(sysFlagInner)) {
- brokerAddr = computPullFromWhichFilterServer(mq.getTopic(), brokerAddr);
+ brokerAddr = computePullFromWhichFilterServer(mq.getTopic(), brokerAddr);
}
PullResult pullResult = this.mQClientFactory.getMQClientAPIImpl().pullMessage(
@@ -223,7 +223,7 @@ public class PullAPIWrapper {
return MixAll.MASTER_ID;
}
- private String computPullFromWhichFilterServer(final String topic, final String brokerAddr)
+ private String computePullFromWhichFilterServer(final String topic, final String brokerAddr)
throws MQClientException {
ConcurrentMap topicRouteTable = this.mQClientFactory.getTopicRouteTable();
if (topicRouteTable != null) {
diff --git a/client/src/main/java/org/apache/rocketmq/client/impl/consumer/PullRequest.java b/client/src/main/java/org/apache/rocketmq/client/impl/consumer/PullRequest.java
index 10aded076252b7513b5eb42c67ebb28136f42930..bf03ec38c3a68d9a789504f3291b9b66d4c833cf 100644
--- a/client/src/main/java/org/apache/rocketmq/client/impl/consumer/PullRequest.java
+++ b/client/src/main/java/org/apache/rocketmq/client/impl/consumer/PullRequest.java
@@ -23,14 +23,14 @@ public class PullRequest {
private MessageQueue messageQueue;
private ProcessQueue processQueue;
private long nextOffset;
- private boolean lockedFirst = false;
+ private boolean previouslyLocked = false;
- public boolean isLockedFirst() {
- return lockedFirst;
+ public boolean isPreviouslyLocked() {
+ return previouslyLocked;
}
- public void setLockedFirst(boolean lockedFirst) {
- this.lockedFirst = lockedFirst;
+ public void setPreviouslyLocked(boolean previouslyLocked) {
+ this.previouslyLocked = previouslyLocked;
}
public String getConsumerGroup() {
diff --git a/client/src/main/java/org/apache/rocketmq/client/impl/consumer/RebalanceImpl.java b/client/src/main/java/org/apache/rocketmq/client/impl/consumer/RebalanceImpl.java
index b8972a92e8fdb3402b92c7c1b1a8015cb38a127b..833d465a4703184be6e9a17c20682fdd5d81b240 100644
--- a/client/src/main/java/org/apache/rocketmq/client/impl/consumer/RebalanceImpl.java
+++ b/client/src/main/java/org/apache/rocketmq/client/impl/consumer/RebalanceImpl.java
@@ -28,6 +28,7 @@ import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import org.apache.rocketmq.client.consumer.AllocateMessageQueueStrategy;
+import org.apache.rocketmq.client.exception.MQClientException;
import org.apache.rocketmq.client.impl.FindBrokerResult;
import org.apache.rocketmq.client.impl.factory.MQClientInstance;
import org.apache.rocketmq.client.log.ClientLogger;
@@ -373,7 +374,15 @@ public abstract class RebalanceImpl {
this.removeDirtyOffset(mq);
ProcessQueue pq = new ProcessQueue();
- long nextOffset = this.computePullFromWhere(mq);
+
+ long nextOffset = -1L;
+ try {
+ nextOffset = this.computePullFromWhereWithException(mq);
+ } catch (MQClientException e) {
+ log.info("doRebalance, {}, compute offset failed, {}", consumerGroup, mq);
+ continue;
+ }
+
if (nextOffset >= 0) {
ProcessQueue pre = this.processQueueTable.putIfAbsent(mq, pq);
if (pre != null) {
@@ -408,8 +417,17 @@ public abstract class RebalanceImpl {
public abstract void removeDirtyOffset(final MessageQueue mq);
+ /**
+ * When the network is unstable, using this interface may return wrong offset.
+ * It is recommended to use computePullFromWhereWithException instead.
+ * @param mq
+ * @return offset
+ */
+ @Deprecated
public abstract long computePullFromWhere(final MessageQueue mq);
+ public abstract long computePullFromWhereWithException(final MessageQueue mq) throws MQClientException;
+
public abstract void dispatchPullRequest(final List pullRequestList);
public void removeProcessQueue(final MessageQueue mq) {
diff --git a/client/src/main/java/org/apache/rocketmq/client/impl/consumer/RebalanceLitePullImpl.java b/client/src/main/java/org/apache/rocketmq/client/impl/consumer/RebalanceLitePullImpl.java
index 9d1ea7492eea2ffc662defea11f4fe5d1bf84f38..286c684e43a52dc3759c0f3b9393e0ee75851ef4 100644
--- a/client/src/main/java/org/apache/rocketmq/client/impl/consumer/RebalanceLitePullImpl.java
+++ b/client/src/main/java/org/apache/rocketmq/client/impl/consumer/RebalanceLitePullImpl.java
@@ -74,8 +74,20 @@ public class RebalanceLitePullImpl extends RebalanceImpl {
this.litePullConsumerImpl.getOffsetStore().removeOffset(mq);
}
+ @Deprecated
@Override
public long computePullFromWhere(MessageQueue mq) {
+ long result = -1L;
+ try {
+ result = computePullFromWhereWithException(mq);
+ } catch (MQClientException e) {
+ log.warn("Compute consume offset exception, mq={}", mq);
+ }
+ return result;
+ }
+
+ @Override
+ public long computePullFromWhereWithException(MessageQueue mq) throws MQClientException {
ConsumeFromWhere consumeFromWhere = litePullConsumerImpl.getDefaultLitePullConsumer().getConsumeFromWhere();
long result = -1;
switch (consumeFromWhere) {
@@ -118,7 +130,8 @@ public class RebalanceLitePullImpl extends RebalanceImpl {
try {
result = this.mQClientFactory.getMQAdminImpl().maxOffset(mq);
} catch (MQClientException e) {
- result = -1;
+ log.warn("Compute consume offset from last offset exception, mq={}, exception={}", mq, e);
+ throw e;
}
} else {
try {
@@ -126,7 +139,8 @@ public class RebalanceLitePullImpl extends RebalanceImpl {
UtilAll.YYYYMMDDHHMMSS).getTime();
result = this.mQClientFactory.getMQAdminImpl().searchOffset(mq, timestamp);
} catch (MQClientException e) {
- result = -1;
+ log.warn("Compute consume offset from last offset exception, mq={}, exception={}", mq, e);
+ throw e;
}
}
} else {
diff --git a/client/src/main/java/org/apache/rocketmq/client/impl/consumer/RebalancePullImpl.java b/client/src/main/java/org/apache/rocketmq/client/impl/consumer/RebalancePullImpl.java
index 9dd408c1d140ea4f7ce4aa31df5e5181c997b753..6df7eb7f00cb3141bda3cef444f6a88c7abeeadd 100644
--- a/client/src/main/java/org/apache/rocketmq/client/impl/consumer/RebalancePullImpl.java
+++ b/client/src/main/java/org/apache/rocketmq/client/impl/consumer/RebalancePullImpl.java
@@ -20,6 +20,7 @@ import java.util.List;
import java.util.Set;
import org.apache.rocketmq.client.consumer.AllocateMessageQueueStrategy;
import org.apache.rocketmq.client.consumer.MessageQueueListener;
+import org.apache.rocketmq.client.exception.MQClientException;
import org.apache.rocketmq.client.impl.factory.MQClientInstance;
import org.apache.rocketmq.common.message.MessageQueue;
import org.apache.rocketmq.common.protocol.heartbeat.ConsumeType;
@@ -68,11 +69,17 @@ public class RebalancePullImpl extends RebalanceImpl {
this.defaultMQPullConsumerImpl.getOffsetStore().removeOffset(mq);
}
+ @Deprecated
@Override
public long computePullFromWhere(MessageQueue mq) {
return 0;
}
+ @Override
+ public long computePullFromWhereWithException(MessageQueue mq) throws MQClientException {
+ return 0;
+ }
+
@Override
public void dispatchPullRequest(List pullRequestList) {
}
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 e5166f35b59c003d4512f6f2e64965713ea8d051..666b696ffa89a631243e2e6533cfa82a52ff383f 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, {}",
@@ -137,8 +137,20 @@ public class RebalancePushImpl extends RebalanceImpl {
this.defaultMQPushConsumerImpl.getOffsetStore().removeOffset(mq);
}
+ @Deprecated
@Override
public long computePullFromWhere(MessageQueue mq) {
+ long result = -1L;
+ try {
+ result = computePullFromWhereWithException(mq);
+ } catch (MQClientException e) {
+ log.warn("Compute consume offset exception, mq={}", mq);
+ }
+ return result;
+ }
+
+ @Override
+ public long computePullFromWhereWithException(MessageQueue mq) throws MQClientException {
long result = -1;
final ConsumeFromWhere consumeFromWhere = this.defaultMQPushConsumerImpl.getDefaultMQPushConsumer().getConsumeFromWhere();
final OffsetStore offsetStore = this.defaultMQPushConsumerImpl.getOffsetStore();
@@ -159,7 +171,8 @@ public class RebalancePushImpl extends RebalanceImpl {
try {
result = this.mQClientFactory.getMQAdminImpl().maxOffset(mq);
} catch (MQClientException e) {
- result = -1;
+ log.warn("Compute consume offset from last offset exception, mq={}, exception={}", mq, e);
+ throw e;
}
}
} else {
@@ -187,7 +200,8 @@ public class RebalancePushImpl extends RebalanceImpl {
try {
result = this.mQClientFactory.getMQAdminImpl().maxOffset(mq);
} catch (MQClientException e) {
- result = -1;
+ log.warn("Compute consume offset from last offset exception, mq={}, exception={}", mq, e);
+ throw e;
}
} else {
try {
@@ -195,7 +209,8 @@ public class RebalancePushImpl extends RebalanceImpl {
UtilAll.YYYYMMDDHHMMSS).getTime();
result = this.mQClientFactory.getMQAdminImpl().searchOffset(mq, timestamp);
} catch (MQClientException e) {
- result = -1;
+ log.warn("Compute consume offset from last offset exception, mq={}, exception={}", mq, e);
+ throw e;
}
}
} else {
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 886203fe7d405ec9dede6ecbf6165cedaed72d13..81e6d8468ebf1d303330cd4ff21b91f79be58b8a 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
@@ -475,7 +475,7 @@ public class MQClientInstance {
this.lockHeartbeat.unlock();
}
} else {
- log.warn("lock heartBeat, but failed.");
+ log.warn("lock heartBeat, but failed. [{}]", this.clientId);
}
}
@@ -532,7 +532,7 @@ public class MQClientInstance {
final boolean producerEmpty = heartbeatData.getProducerDataSet().isEmpty();
final boolean consumerEmpty = heartbeatData.getConsumerDataSet().isEmpty();
if (producerEmpty && consumerEmpty) {
- log.warn("sending heartbeat, but no consumer and no producer");
+ log.warn("sending heartbeat, but no consumer and no producer. [{}]", this.clientId);
return;
}
@@ -668,10 +668,10 @@ public class MQClientInstance {
return true;
}
} else {
- log.warn("updateTopicRouteInfoFromNameServer, getTopicRouteInfoFromNameServer return null, Topic: {}", topic);
+ log.warn("updateTopicRouteInfoFromNameServer, getTopicRouteInfoFromNameServer return null, Topic: {}. [{}]", topic, this.clientId);
}
} catch (MQClientException e) {
- if (!topic.startsWith(MixAll.RETRY_GROUP_TOPIC_PREFIX) && !topic.equals(MixAll.AUTO_CREATE_TOPIC_KEY_TOPIC)) {
+ if (!topic.startsWith(MixAll.RETRY_GROUP_TOPIC_PREFIX)) {
log.warn("updateTopicRouteInfoFromNameServer Exception", e);
}
} catch (RemotingException e) {
@@ -681,7 +681,7 @@ public class MQClientInstance {
this.lockNamesrv.unlock();
}
} else {
- log.warn("updateTopicRouteInfoFromNameServer tryLock timeout {}ms", LOCK_TIMEOUT_MILLIS);
+ log.warn("updateTopicRouteInfoFromNameServer tryLock timeout {}ms. [{}]", LOCK_TIMEOUT_MILLIS, this.clientId);
}
} catch (InterruptedException e) {
log.warn("updateTopicRouteInfoFromNameServer Exception", e);
@@ -893,7 +893,7 @@ public class MQClientInstance {
this.lockHeartbeat.unlock();
}
} else {
- log.warn("lock heartBeat, but failed.");
+ log.warn("lock heartBeat, but failed. [{}]", this.clientId);
}
} catch (InterruptedException e) {
log.warn("unregisterClientWithLock exception", e);
@@ -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 bff1457835fba85421573039410b2c79aeae6d8e..fac3ed3561f2003da0d3be1855b7995af62bd8f6 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,
@@ -421,6 +430,7 @@ public class DefaultMQProducerImpl implements MQProducerInner {
public void createTopic(String key, String newTopic, int queueNum, int topicSysFlag) throws MQClientException {
this.makeSureStateOK();
Validators.checkTopic(newTopic);
+ Validators.isSystemTopic(newTopic);
this.mQClientFactory.getMQAdminImpl().createTopic(key, newTopic, queueNum, topicSysFlag);
}
@@ -966,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 -------------------------------------------------------
*/
@@ -1114,7 +1154,7 @@ public class DefaultMQProducerImpl implements MQProducerInner {
mq = mQClientFactory.getClientConfig().queueWithNamespace(selector.select(messageQueueList, userMessage, arg));
} catch (Throwable e) {
- throw new MQClientException("select message queue throwed exception.", e);
+ throw new MQClientException("select message queue threw exception.", e);
}
long costTime = System.currentTimeMillis() - beginStartTime;
@@ -1265,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);
}
@@ -1289,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 {
@@ -1317,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 deb02cff285b42c241e4c064ad376d47ebdecfa8..2f8337edefdd099805ad6ae9dec78faf17d6887e 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 72d43476f8371920e78153886b5ec4cff100f196..827d97265f51319a2fcc523e2b80f9062a3ef093 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 7854fcb7d10905602e27ac06d6cb9326e82e2b86..ea3d07e6d0f5028dcc35df88b6729754623367c2 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,16 +58,14 @@ 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)
pos = 0;
MessageQueue mq = tpInfo.getMessageQueueList().get(pos);
- if (latencyFaultTolerance.isAvailable(mq.getBrokerName())) {
- if (null == lastBrokerName || mq.getBrokerName().equals(lastBrokerName))
- return mq;
- }
+ if (latencyFaultTolerance.isAvailable(mq.getBrokerName()))
+ return mq;
}
final String notBestBroker = latencyFaultTolerance.pickOneAtLeast();
@@ -76,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 045734103f571e798508e4dfab3eaac738586c5e..1c4a9315a8cd95c6c2aa0b1fd62c25091fa4213c 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;
@@ -38,6 +39,7 @@ import org.apache.rocketmq.common.message.MessageDecoder;
import org.apache.rocketmq.common.message.MessageExt;
import org.apache.rocketmq.common.message.MessageId;
import org.apache.rocketmq.common.message.MessageQueue;
+import org.apache.rocketmq.common.topic.TopicValidator;
import org.apache.rocketmq.logging.InternalLogger;
import org.apache.rocketmq.remoting.RPCHook;
import org.apache.rocketmq.remoting.exception.RemotingException;
@@ -74,7 +76,7 @@ public class DefaultMQProducer extends ClientConfig implements MQProducer {
/**
* Just for testing or demo program
*/
- private String createTopicKey = MixAll.AUTO_CREATE_TOPIC_KEY_TOPIC;
+ private String createTopicKey = TopicValidator.AUTO_CREATE_TOPIC_KEY_TOPIC;
/**
* Number of queues to create per default topic.
@@ -166,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");
}
@@ -251,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,6 +922,29 @@ public class DefaultMQProducer extends ClientConfig implements MQProducer {
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 {
+ this.defaultMQProducerImpl.send(batch(msgs), queueWithNamespace(mq), sendCallback, timeout);
+ }
+
/**
* Sets an Executor to be used for executing callback methods. If the Executor is not set, {@link
* NettyRemotingClient#publicExecutor} will be used.
diff --git a/client/src/main/java/org/apache/rocketmq/client/producer/MQProducer.java b/client/src/main/java/org/apache/rocketmq/client/producer/MQProducer.java
index c6cf4c93596578e958de17815fa9604e2c09b7fe..f70ddb283da9e32093f37fcc58e23c6c5afa2aff 100644
--- a/client/src/main/java/org/apache/rocketmq/client/producer/MQProducer.java
+++ b/client/src/main/java/org/apache/rocketmq/client/producer/MQProducer.java
@@ -99,7 +99,19 @@ public interface MQProducer extends MQAdmin {
SendResult send(final Collection msgs, final MessageQueue mq, final long timeout)
throws MQClientException, RemotingException, MQBrokerException, InterruptedException;
-
+
+ void send(final Collection msgs, final SendCallback sendCallback) throws MQClientException, RemotingException, MQBrokerException,
+ InterruptedException;
+
+ void send(final Collection msgs, final SendCallback sendCallback, final long timeout) throws MQClientException, RemotingException,
+ MQBrokerException, InterruptedException;
+
+ void send(final Collection msgs, final MessageQueue mq, final SendCallback sendCallback) throws MQClientException, RemotingException,
+ MQBrokerException, InterruptedException;
+
+ void send(final Collection msgs, final MessageQueue mq, final SendCallback sendCallback, final long timeout) throws MQClientException,
+ RemotingException, MQBrokerException, InterruptedException;
+
//for rpc
Message request(final Message msg, final long timeout) throws RequestTimeoutException, 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 63b512df7d5374857624d81892acdf2c61252814..4eb758df401f2eea5224c75b85c8b0972339b059 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 11e2822b225a3afb1ab535d623c0eb262cdcc1bb..ba8ea8b58a30ec86113ad962a0630b526c9b5b24 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/stat/ConsumerStatsManager.java b/client/src/main/java/org/apache/rocketmq/client/stat/ConsumerStatsManager.java
index cf347b4dd7e68c3b80d095662e7d447a3d0708ba..ba4773ae679355cced2d8bc4579aed0ec92b291d 100644
--- a/client/src/main/java/org/apache/rocketmq/client/stat/ConsumerStatsManager.java
+++ b/client/src/main/java/org/apache/rocketmq/client/stat/ConsumerStatsManager.java
@@ -62,7 +62,7 @@ public class ConsumerStatsManager {
}
public void incPullRT(final String group, final String topic, final long rt) {
- this.topicAndGroupPullRT.addValue(topic + "@" + group, (int) rt, 1);
+ this.topicAndGroupPullRT.addRTValue(topic + "@" + group, (int) rt, 1);
}
public void incPullTPS(final String group, final String topic, final long msgs) {
@@ -70,7 +70,7 @@ public class ConsumerStatsManager {
}
public void incConsumeRT(final String group, final String topic, final long rt) {
- this.topicAndGroupConsumeRT.addValue(topic + "@" + group, (int) rt, 1);
+ this.topicAndGroupConsumeRT.addRTValue(topic + "@" + group, (int) rt, 1);
}
public void incConsumeOKTPS(final String group, final String topic, final long msgs) {
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 8c3d886517595ce2fb53d1012735d8fb7af32b50..7ff8bd77e03152f2469db28ee90891ff1dd59be3 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
@@ -16,7 +16,6 @@
*/
package org.apache.rocketmq.client.trace;
-import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
@@ -28,7 +27,9 @@ import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
+
import org.apache.commons.lang3.StringUtils;
import org.apache.rocketmq.client.AccessChannel;
import org.apache.rocketmq.client.common.ThreadLocalIndex;
@@ -41,11 +42,11 @@ import org.apache.rocketmq.client.producer.DefaultMQProducer;
import org.apache.rocketmq.client.producer.MessageQueueSelector;
import org.apache.rocketmq.client.producer.SendCallback;
import org.apache.rocketmq.client.producer.SendResult;
-import org.apache.rocketmq.common.MixAll;
import org.apache.rocketmq.common.ThreadFactoryImpl;
import org.apache.rocketmq.common.UtilAll;
import org.apache.rocketmq.common.message.Message;
import org.apache.rocketmq.common.message.MessageQueue;
+import org.apache.rocketmq.common.topic.TopicValidator;
import org.apache.rocketmq.logging.InternalLogger;
import org.apache.rocketmq.remoting.RPCHook;
@@ -54,6 +55,7 @@ import static org.apache.rocketmq.client.trace.TraceConstants.TRACE_INSTANCE_NAM
public class AsyncTraceDispatcher implements TraceDispatcher {
private final static InternalLogger log = ClientLogger.getLog();
+ private final static AtomicInteger COUNTER = new AtomicInteger();
private final int queueSize;
private final int batchSize;
private final int maxMsgSize;
@@ -62,7 +64,7 @@ public class AsyncTraceDispatcher implements TraceDispatcher {
// The last discard number of log
private AtomicLong discardCount;
private Thread worker;
- private ArrayBlockingQueue traceContextQueue;
+ private final ArrayBlockingQueue traceContextQueue;
private ArrayBlockingQueue appenderQueue;
private volatile Thread shutDownHook;
private volatile boolean stopped = false;
@@ -76,7 +78,7 @@ public class AsyncTraceDispatcher implements TraceDispatcher {
private String group;
private Type type;
- public AsyncTraceDispatcher(String group, Type type,String traceTopicName, RPCHook rpcHook) {
+ public AsyncTraceDispatcher(String group, Type type, String traceTopicName, RPCHook rpcHook) {
// queueSize is greater than or equal to the n power of 2 of value
this.queueSize = 2048;
this.batchSize = 100;
@@ -90,15 +92,15 @@ public class AsyncTraceDispatcher implements TraceDispatcher {
if (!UtilAll.isBlank(traceTopicName)) {
this.traceTopicName = traceTopicName;
} else {
- this.traceTopicName = MixAll.RMQ_SYS_TRACE_TOPIC;
+ this.traceTopicName = TopicValidator.RMQ_SYS_TRACE_TOPIC;
}
this.traceExecutor = new ThreadPoolExecutor(//
- 10, //
- 20, //
- 1000 * 60, //
- TimeUnit.MILLISECONDS, //
- this.appenderQueue, //
- new ThreadFactoryImpl("MQTraceSendThread_"));
+ 10, //
+ 20, //
+ 1000 * 60, //
+ TimeUnit.MILLISECONDS, //
+ this.appenderQueue, //
+ new ThreadFactoryImpl("MQTraceSendThread_"));
traceProducer = getAndCreateTraceProducer(rpcHook);
}
@@ -165,7 +167,7 @@ public class AsyncTraceDispatcher implements TraceDispatcher {
}
private String genGroupNameForTrace() {
- return TraceConstants.GROUP_NAME_PREFIX + "-" + this.group + "-" + this.type ;
+ return TraceConstants.GROUP_NAME_PREFIX + "-" + this.group + "-" + this.type + "-" + COUNTER.incrementAndGet();
}
@Override
@@ -178,10 +180,15 @@ public class AsyncTraceDispatcher implements TraceDispatcher {
}
@Override
- public void flush() throws IOException {
+ public void flush() {
// The maximum waiting time for refresh,avoid being written all the time, resulting in failure to return.
long end = System.currentTimeMillis() + 500;
- while (traceContextQueue.size() > 0 || appenderQueue.size() > 0 && System.currentTimeMillis() <= end) {
+ while (System.currentTimeMillis() <= end) {
+ synchronized (traceContextQueue) {
+ if (traceContextQueue.size() == 0 && appenderQueue.size() == 0) {
+ break;
+ }
+ }
try {
Thread.sleep(1);
} catch (InterruptedException e) {
@@ -194,6 +201,7 @@ public class AsyncTraceDispatcher implements TraceDispatcher {
@Override
public void shutdown() {
this.stopped = true;
+ flush();
this.traceExecutor.shutdown();
if (isStarted.get()) {
traceProducer.shutdown();
@@ -210,11 +218,7 @@ public class AsyncTraceDispatcher implements TraceDispatcher {
public void run() {
synchronized (this) {
if (!this.hasShutdown) {
- try {
- flush();
- } catch (IOException e) {
- log.error("system MQTrace hook shutdown failed ,maybe loss some trace data");
- }
+ flush();
}
}
}
@@ -240,25 +244,27 @@ public class AsyncTraceDispatcher implements TraceDispatcher {
public void run() {
while (!stopped) {
List contexts = new ArrayList(batchSize);
- for (int i = 0; i < batchSize; i++) {
- TraceContext context = null;
- try {
- //get trace data element from blocking Queue — traceContextQueue
- context = traceContextQueue.poll(5, TimeUnit.MILLISECONDS);
- } catch (InterruptedException e) {
+ synchronized (traceContextQueue) {
+ for (int i = 0; i < batchSize; i++) {
+ TraceContext context = null;
+ try {
+ //get trace data element from blocking Queue - traceContextQueue
+ context = traceContextQueue.poll(5, TimeUnit.MILLISECONDS);
+ } catch (InterruptedException e) {
+ }
+ if (context != null) {
+ contexts.add(context);
+ } else {
+ break;
+ }
}
- if (context != null) {
- contexts.add(context);
- } else {
- break;
+ if (contexts.size() > 0) {
+ AsyncAppenderRequest request = new AsyncAppenderRequest(contexts);
+ traceExecutor.submit(request);
+ } else if (AsyncTraceDispatcher.this.stopped) {
+ this.stopped = true;
}
}
- if (contexts.size() > 0) {
- AsyncAppenderRequest request = new AsyncAppenderRequest(contexts);
- traceExecutor.submit(request);
- } else if (AsyncTraceDispatcher.this.stopped) {
- this.stopped = true;
- }
}
}
@@ -350,7 +356,7 @@ public class AsyncTraceDispatcher implements TraceDispatcher {
* Send message trace data
*
* @param keySet the keyset in this batch(including msgId in original message not offsetMsgId)
- * @param data the message trace data in this batch
+ * @param data the message trace data in this batch
*/
private void sendTraceDataByMQ(Set keySet, final String data, String dataTopic, String regionId) {
String traceTopic = traceTopicName;
@@ -370,7 +376,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 +393,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 +404,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 f93aa38b8293712b56a9af289c15d3586f67e76e..70c147e1eb349649cf76afc91b1bf661a619c7d1 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 cb4a246517d62e711bd7b7dd171fb4e97d575482..1ad4b6105153d4dd4e167887dc54d3bee451bb56 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
@@ -16,7 +16,7 @@
*/
package org.apache.rocketmq.client.trace;
-import org.apache.rocketmq.common.MixAll;
+import org.apache.rocketmq.common.topic.TopicValidator;
public class TraceConstants {
@@ -24,5 +24,21 @@ public class TraceConstants {
public static final char CONTENT_SPLITOR = (char) 1;
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 = MixAll.SYSTEM_TOPIC_PREFIX + "TRACE_DATA_";
+ 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 5a1afaf3617a5922eb122a829e31f3ab3fbbe184..10aa2413591309fc72b17f090b7b84af548deb86 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;
@@ -62,6 +63,14 @@ public class TraceDataEncoder {
bean.setOffsetMsgId(line[12]);
pubContext.setSuccess(Boolean.parseBoolean(line[13]));
}
+
+ // compatible with the old version
+ if (line.length >= 15) {
+ bean.setOffsetMsgId(line[12]);
+ pubContext.setSuccess(Boolean.parseBoolean(line[13]));
+ bean.setClientHost(line[14]);
+ }
+
pubContext.setTraceBeans(new ArrayList(1));
pubContext.getTraceBeans().add(bean);
resList.add(pubContext);
@@ -94,7 +103,32 @@ public class TraceDataEncoder {
// add the context type
subAfterContext.setContextCode(Integer.parseInt(line[6]));
}
+ // compatible with the old version
+ if (line.length >= 9) {
+ subAfterContext.setTimeStamp(Long.parseLong(line[7]));
+ 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.setTransactionId(line[10]);
+ bean.setTransactionState(LocalTransactionState.valueOf(line[11]));
+ bean.setFromTransactionCheck(Boolean.parseBoolean(line[12]));
+
+ endTransactionContext.setTraceBeans(new ArrayList(1));
+ endTransactionContext.getTraceBeans().add(bean);
+ resList.add(endTransactionContext);
}
}
return resList;
@@ -130,7 +164,7 @@ public class TraceDataEncoder {
.append(ctx.getCostTime()).append(TraceConstants.CONTENT_SPLITOR)//
.append(bean.getMsgType().ordinal()).append(TraceConstants.CONTENT_SPLITOR)//
.append(bean.getOffsetMsgId()).append(TraceConstants.CONTENT_SPLITOR)//
- .append(ctx.isSuccess()).append(TraceConstants.FIELD_SPLITOR);
+ .append(ctx.isSuccess()).append(TraceConstants.FIELD_SPLITOR);//
}
break;
case SubBefore: {
@@ -155,9 +189,27 @@ public class TraceDataEncoder {
.append(ctx.isSuccess()).append(TraceConstants.CONTENT_SPLITOR)//
.append(bean.getKeys()).append(TraceConstants.CONTENT_SPLITOR)//
.append(ctx.getContextCode()).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.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 79b19c17e4e53e4213a456fb4862089d6a0a0920..8870ddcbdb3ef0e6a4ea3b35247891db30157e6d 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/TraceView.java b/client/src/main/java/org/apache/rocketmq/client/trace/TraceView.java
new file mode 100644
index 0000000000000000000000000000000000000000..e78d37ab2cdbd4c5f0ece7d43aca814f1f44eb20
--- /dev/null
+++ b/client/src/main/java/org/apache/rocketmq/client/trace/TraceView.java
@@ -0,0 +1,180 @@
+/*
+ * 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;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.commons.codec.Charsets;
+import org.apache.rocketmq.common.message.MessageExt;
+
+public class TraceView {
+
+ private String msgId;
+ private String tags;
+ private String keys;
+ private String storeHost;
+ private String clientHost;
+ private int costTime;
+ private String msgType;
+ private String offSetMsgId;
+ private long timeStamp;
+ private long bornTime;
+ private String topic;
+ private String groupName;
+ private String status;
+
+ public static List decodeFromTraceTransData(String key, MessageExt messageExt) {
+ List messageTraceViewList = new ArrayList();
+ String messageBody = new String(messageExt.getBody(), Charsets.UTF_8);
+ if (messageBody == null || messageBody.length() <= 0) {
+ return messageTraceViewList;
+ }
+
+ List traceContextList = TraceDataEncoder.decoderFromTraceDataString(messageBody);
+
+ for (TraceContext context : traceContextList) {
+ TraceView messageTraceView = new TraceView();
+ TraceBean traceBean = context.getTraceBeans().get(0);
+ if (!traceBean.getMsgId().equals(key)) {
+ continue;
+ }
+ messageTraceView.setCostTime(context.getCostTime());
+ messageTraceView.setGroupName(context.getGroupName());
+ if (context.isSuccess()) {
+ messageTraceView.setStatus("success");
+ } else {
+ messageTraceView.setStatus("failed");
+ }
+ messageTraceView.setKeys(traceBean.getKeys());
+ messageTraceView.setMsgId(traceBean.getMsgId());
+ messageTraceView.setTags(traceBean.getTags());
+ messageTraceView.setTopic(traceBean.getTopic());
+ messageTraceView.setMsgType(context.getTraceType().name());
+ messageTraceView.setOffSetMsgId(traceBean.getOffsetMsgId());
+ messageTraceView.setTimeStamp(context.getTimeStamp());
+ messageTraceView.setStoreHost(traceBean.getStoreHost());
+ messageTraceView.setClientHost(messageExt.getBornHostString());
+ messageTraceViewList.add(messageTraceView);
+ }
+ return messageTraceViewList;
+ }
+
+ public String getMsgId() {
+ return msgId;
+ }
+
+ public void setMsgId(String msgId) {
+ this.msgId = msgId;
+ }
+
+ public String getTags() {
+ return tags;
+ }
+
+ public void setTags(String tags) {
+ this.tags = tags;
+ }
+
+ public String getKeys() {
+ return keys;
+ }
+
+ public void setKeys(String keys) {
+ this.keys = keys;
+ }
+
+ public String getStoreHost() {
+ return storeHost;
+ }
+
+ public void setStoreHost(String storeHost) {
+ this.storeHost = storeHost;
+ }
+
+ public String getClientHost() {
+ return clientHost;
+ }
+
+ public void setClientHost(String clientHost) {
+ this.clientHost = clientHost;
+ }
+
+ public int getCostTime() {
+ return costTime;
+ }
+
+ public void setCostTime(int costTime) {
+ this.costTime = costTime;
+ }
+
+ public String getMsgType() {
+ return msgType;
+ }
+
+ public void setMsgType(String msgType) {
+ this.msgType = msgType;
+ }
+
+ public String getOffSetMsgId() {
+ return offSetMsgId;
+ }
+
+ public void setOffSetMsgId(String offSetMsgId) {
+ this.offSetMsgId = offSetMsgId;
+ }
+
+ public long getTimeStamp() {
+ return timeStamp;
+ }
+
+ public void setTimeStamp(long timeStamp) {
+ this.timeStamp = timeStamp;
+ }
+
+ public long getBornTime() {
+ return bornTime;
+ }
+
+ public void setBornTime(long bornTime) {
+ this.bornTime = bornTime;
+ }
+
+ public String getTopic() {
+ return topic;
+ }
+
+ public void setTopic(String topic) {
+ this.topic = topic;
+ }
+
+ public String getGroupName() {
+ return groupName;
+ }
+
+ public void setGroupName(String groupName) {
+ this.groupName = groupName;
+ }
+
+ public String getStatus() {
+ return status;
+ }
+
+ public void setStatus(String status) {
+ this.status = status;
+ }
+}
\ No newline at end of file
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 0000000000000000000000000000000000000000..28fccae06f8d358925ff3e539ee0cf1c4c0ed52d
--- /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/ConsumeMessageTraceHookImpl.java b/client/src/main/java/org/apache/rocketmq/client/trace/hook/ConsumeMessageTraceHookImpl.java
index f30b1211f9413c4531dcedcc228e491a4c8aeecc..bce613987ff65753ffca83a99ef2cbc9fadc11a6 100644
--- a/client/src/main/java/org/apache/rocketmq/client/trace/hook/ConsumeMessageTraceHookImpl.java
+++ b/client/src/main/java/org/apache/rocketmq/client/trace/hook/ConsumeMessageTraceHookImpl.java
@@ -16,6 +16,7 @@
*/
package org.apache.rocketmq.client.trace.hook;
+import java.util.Map;
import org.apache.rocketmq.client.consumer.listener.ConsumeReturnType;
import org.apache.rocketmq.client.hook.ConsumeMessageContext;
import org.apache.rocketmq.client.hook.ConsumeMessageHook;
@@ -91,7 +92,7 @@ public class ConsumeMessageTraceHookImpl implements ConsumeMessageHook {
TraceContext subBeforeContext = (TraceContext) context.getMqTraceContext();
if (subBeforeContext.getTraceBeans() == null || subBeforeContext.getTraceBeans().size() < 1) {
- // If subbefore bean is null ,skip it
+ // If subBefore bean is null ,skip it
return;
}
TraceContext subAfterContext = new TraceContext();
@@ -101,13 +102,16 @@ public class ConsumeMessageTraceHookImpl implements ConsumeMessageHook {
subAfterContext.setRequestId(subBeforeContext.getRequestId());//
subAfterContext.setSuccess(context.isSuccess());//
- // Caculate the cost time for processing messages
+ // Calculate the cost time for processing messages
int costTime = (int) ((System.currentTimeMillis() - subBeforeContext.getTimeStamp()) / context.getMsgList().size());
subAfterContext.setCostTime(costTime);//
subAfterContext.setTraceBeans(subBeforeContext.getTraceBeans());
- String contextType = context.getProps().get(MixAll.CONSUME_CONTEXT_TYPE);
- if (contextType != null) {
- subAfterContext.setContextCode(ConsumeReturnType.valueOf(contextType).ordinal());
+ Map props = context.getProps();
+ if (props != null) {
+ String contextType = props.get(MixAll.CONSUME_CONTEXT_TYPE);
+ if (contextType != null) {
+ subAfterContext.setContextCode(ConsumeReturnType.valueOf(contextType).ordinal());
+ }
}
localDispatcher.append(subAfterContext);
}
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 0000000000000000000000000000000000000000..62d310f1961f0971f11803367d9d83b04a8ee7b0
--- /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 0000000000000000000000000000000000000000..cbd755ba39e19a65386ec65252a9f1f817e486fd
--- /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 0000000000000000000000000000000000000000..60c18a22a77ad8f265ebfb38ca91c239dce8a01d
--- /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/ValidatorsTest.java b/client/src/test/java/org/apache/rocketmq/client/ValidatorsTest.java
index e2b9abd46f045bdefbc4f78bdc8112ac899b4563..343fe4bca69707da07858e84daea2d0927cd6722 100644
--- a/client/src/test/java/org/apache/rocketmq/client/ValidatorsTest.java
+++ b/client/src/test/java/org/apache/rocketmq/client/ValidatorsTest.java
@@ -19,11 +19,12 @@ package org.apache.rocketmq.client;
import org.apache.commons.lang3.StringUtils;
import org.apache.rocketmq.client.exception.MQClientException;
-import org.apache.rocketmq.common.MixAll;
+import org.apache.rocketmq.common.topic.TopicValidator;
import org.junit.Test;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Fail.failBecauseExceptionWasNotThrown;
+import static org.junit.Assert.fail;
public class ValidatorsTest {
@@ -47,17 +48,6 @@ public class ValidatorsTest {
}
}
- @Test
- public void testCheckTopic_UseDefaultTopic() {
- String defaultTopic = MixAll.AUTO_CREATE_TOPIC_KEY_TOPIC;
- try {
- Validators.checkTopic(defaultTopic);
- failBecauseExceptionWasNotThrown(MQClientException.class);
- } catch (MQClientException e) {
- assertThat(e).hasMessageStartingWith(String.format("The topic[%s] is conflict with AUTO_CREATE_TOPIC_KEY_TOPIC.", defaultTopic));
- }
- }
-
@Test
public void testCheckTopic_BlankTopic() {
String blankTopic = "";
@@ -80,4 +70,30 @@ public class ValidatorsTest {
assertThat(e).hasMessageStartingWith("The specified topic is longer than topic max length");
}
}
+
+ @Test
+ public void testIsSystemTopic() {
+ for (String topic : TopicValidator.getSystemTopicSet()) {
+ try {
+ Validators.isSystemTopic(topic);
+ fail("excepted MQClientException for system topic");
+ } catch (MQClientException e) {
+ assertThat(e.getResponseCode()).isEqualTo(-1);
+ assertThat(e.getErrorMessage()).isEqualTo(String.format("The topic[%s] is conflict with system topic.", topic));
+ }
+ }
+ }
+
+ @Test
+ public void testIsNotAllowedSendTopic() {
+ for (String topic : TopicValidator.getNotAllowedSendTopicSet()) {
+ try {
+ Validators.isNotAllowedSendTopic(topic);
+ fail("excepted MQClientException for blacklist topic");
+ } catch (MQClientException e) {
+ assertThat(e.getResponseCode()).isEqualTo(-1);
+ assertThat(e.getErrorMessage()).isEqualTo(String.format("Sending message to topic[%s] is forbidden.", topic));
+ }
+ }
+ }
}
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 1be93ce0f3a1dd6d557d841c85109f3410bc40c6..de35b9181b6024eb16b8678f9314da6bc95e4316 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 cc8d5e2bf78a8ba0c840c1ec4e1045b89f931009..04b760eec2281561a70c7723208f10d1125d457f 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
@@ -24,6 +24,8 @@ 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;
@@ -48,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;
@@ -71,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());
@@ -81,6 +81,8 @@ public class DefaultLitePullConsumerTest {
private MQClientAPIImpl mQClientAPIImpl;
@Mock
private MQAdminImpl mQAdminImpl;
+ @Mock
+ private AssignedMessageQueue assignedMQ;
private RebalanceImpl rebalanceImpl;
private OffsetStore offsetStore;
@@ -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);
@@ -304,6 +317,53 @@ public class DefaultLitePullConsumerTest {
}
}
+ @Test
+ public void testPullTaskImpl_ProcessQueueNull() throws Exception {
+ DefaultLitePullConsumer litePullConsumer = createNotStartLitePullConsumer();
+ try {
+ MessageQueue messageQueue = createMessageQueue();
+ litePullConsumer.assign(Collections.singletonList(messageQueue));
+ Field field = DefaultLitePullConsumer.class.getDeclaredField("defaultLitePullConsumerImpl");
+ field.setAccessible(true);
+ // set ProcessQueue dropped = true
+ DefaultLitePullConsumerImpl localLitePullConsumerImpl = (DefaultLitePullConsumerImpl) field.get(litePullConsumer);
+ field = DefaultLitePullConsumerImpl.class.getDeclaredField("assignedMessageQueue");
+ field.setAccessible(true);
+ when(assignedMQ.isPaused(any(MessageQueue.class))).thenReturn(false);
+ when(assignedMQ.getProcessQueue(any(MessageQueue.class))).thenReturn(null);
+ litePullConsumer.start();
+ field.set(localLitePullConsumerImpl, assignedMQ);
+
+ List result = litePullConsumer.poll(100);
+ assertThat(result.isEmpty()).isTrue();
+ } finally {
+ litePullConsumer.shutdown();
+ }
+ }
+
+ @Test
+ public void testPullTaskImpl_ProcessQueueDropped() throws Exception {
+ DefaultLitePullConsumer litePullConsumer = createNotStartLitePullConsumer();
+ try {
+ MessageQueue messageQueue = createMessageQueue();
+ litePullConsumer.assign(Collections.singletonList(messageQueue));
+ Field field = DefaultLitePullConsumer.class.getDeclaredField("defaultLitePullConsumerImpl");
+ field.setAccessible(true);
+ // set ProcessQueue dropped = true
+ DefaultLitePullConsumerImpl localLitePullConsumerImpl = (DefaultLitePullConsumerImpl) field.get(litePullConsumer);
+ field = DefaultLitePullConsumerImpl.class.getDeclaredField("assignedMessageQueue");
+ field.setAccessible(true);
+ AssignedMessageQueue assignedMessageQueue = (AssignedMessageQueue) field.get(localLitePullConsumerImpl);
+ assignedMessageQueue.getProcessQueue(messageQueue).setDropped(true);
+ litePullConsumer.start();
+
+ List result = litePullConsumer.poll(100);
+ assertThat(result.isEmpty()).isTrue();
+ } finally {
+ litePullConsumer.shutdown();
+ }
+ }
+
@Test
public void testRegisterTopicMessageQueueChangeListener_Success() throws Exception {
flag = false;
@@ -464,6 +524,30 @@ public class DefaultLitePullConsumerTest {
assertThat(offset).isEqualTo(100);
}
+ @Test
+ public void testConsumerAfterShutdown() throws Exception {
+ DefaultLitePullConsumer defaultLitePullConsumer = createSubscribeLitePullConsumer();
+
+ new AsyncConsumer().executeAsync(defaultLitePullConsumer);
+
+ Thread.sleep(100);
+ defaultLitePullConsumer.shutdown();
+ assertThat(defaultLitePullConsumer.isRunning()).isFalse();
+ }
+
+ static class AsyncConsumer {
+ public void executeAsync(final DefaultLitePullConsumer consumer) {
+ new Thread(new Runnable() {
+ @Override
+ public void run() {
+ while (consumer.isRunning()) {
+ List poll = consumer.poll(2 * 1000);
+ }
+ }
+ }).start();
+ }
+ }
+
private void initDefaultLitePullConsumer(DefaultLitePullConsumer litePullConsumer) throws Exception {
Field field = DefaultLitePullConsumer.class.getDeclaredField("defaultLitePullConsumerImpl");
@@ -500,9 +584,9 @@ public class DefaultLitePullConsumerTest {
when(mQClientFactory.getMQClientAPIImpl().pullMessage(anyString(), any(PullMessageRequestHeader.class),
anyLong(), any(CommunicationMode.class), nullable(PullCallback.class)))
- .thenAnswer(new Answer
-
- ch.qos.logback
- logback-core
- true
-
ch.qos.logback
logback-classic
diff --git a/logging/pom.xml b/logging/pom.xml
index b4a52a7b0af14e9eb165f8522cb844de67791335..8ebb24304529e907f918e3e77176b200693d6189 100644
--- a/logging/pom.xml
+++ b/logging/pom.xml
@@ -19,7 +19,7 @@
org.apache.rocketmq
rocketmq-all
- 4.7.1-SNAPSHOT
+ 4.9.1-SNAPSHOT
4.0.0
@@ -27,11 +27,6 @@
rocketmq-logging
rocketmq-logging ${project.version}
-
- 1.6
- 1.6
-
-
org.slf4j
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 487682cd44b171e8d3fff8d41d790d1d2383cb50..0dc81d74e6749bcbcdcfc37b2e80e065faf10f2b 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 f457a69567626f3a8c9b4e852e877976b07d9a13..3ec440bc882bb55b014d567bda8f8447a338955d 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 b6d10497782d9714b989e682ea1a2ea2ccc88a7c..aaba4d6e89d01b64abfcbbe6d33551fc82427645 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 d8ae216588f3fe978da0e95aaeaf2a8a98a44556..01ef5b60fe951dfccff97a80ebd0df8f14cf1b47 100644
--- a/namesrv/pom.xml
+++ b/namesrv/pom.xml
@@ -19,7 +19,7 @@
org.apache.rocketmq
rocketmq-all
- 4.7.1-SNAPSHOT
+ 4.9.1-SNAPSHOT
4.0.0
@@ -29,11 +29,11 @@
- org.apache.rocketmq
+ ${project.groupId}
rocketmq-client
- org.apache.rocketmq
+ ${project.groupId}
rocketmq-tools
@@ -44,10 +44,6 @@
ch.qos.logback
logback-classic
-
- ch.qos.logback
- logback-core
-
org.slf4j
slf4j-api
diff --git a/namesrv/src/main/java/org/apache/rocketmq/namesrv/processor/DefaultRequestProcessor.java b/namesrv/src/main/java/org/apache/rocketmq/namesrv/processor/DefaultRequestProcessor.java
index 44a2b6f2610c57ade7000958633eb4c4ddd9d566..f8bc55e7aab38e1f27abc75c674c28eab0a9d02b 100644
--- a/namesrv/src/main/java/org/apache/rocketmq/namesrv/processor/DefaultRequestProcessor.java
+++ b/namesrv/src/main/java/org/apache/rocketmq/namesrv/processor/DefaultRequestProcessor.java
@@ -140,6 +140,11 @@ public class DefaultRequestProcessor extends AsyncNettyRequestProcessor implemen
final PutKVConfigRequestHeader requestHeader =
(PutKVConfigRequestHeader) request.decodeCommandCustomHeader(PutKVConfigRequestHeader.class);
+ if (requestHeader.getNamespace() == null || requestHeader.getKey() == null) {
+ response.setCode(ResponseCode.SYSTEM_ERROR);
+ response.setRemark("namespace or key is null");
+ return response;
+ }
this.namesrvController.getKvConfigManager().putKVConfig(
requestHeader.getNamespace(),
requestHeader.getKey(),
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 ecd057a29ac28a9cf736ea7bea51d469afe5e1ff..edef87ce2d7e5d18f00610ad2619a55357d7a5d5 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 9fcd708ef9b16e18dc64c45f510c31839f51711f..4688c04043633cf98658a7d7d55cd5dad6459d27 100644
--- a/openmessaging/pom.xml
+++ b/openmessaging/pom.xml
@@ -20,10 +20,10 @@
rocketmq-all
org.apache.rocketmq
- 4.7.1-SNAPSHOT
+ 4.9.1-SNAPSHOT
- 4.0.0
+ 4.0.0
rocketmq-openmessaging
rocketmq-openmessaging ${project.version}
@@ -33,7 +33,7 @@
openmessaging-api
- org.apache.rocketmq
+ ${project.groupId}
rocketmq-client
diff --git a/pom.xml b/pom.xml
index 05f544c7d6ebd9ef7310508536b37e4a3de36c95..b6f1770e2d85c6295c02f5077926e158d1d8f872 100644
--- a/pom.xml
+++ b/pom.xml
@@ -29,15 +29,11 @@
2012
org.apache.rocketmq
rocketmq-all
- 4.7.1-SNAPSHOT
+ 4.9.1-SNAPSHOT
pom
Apache RocketMQ ${project.version}
http://rocketmq.apache.org/
-
- 3.2.5
-
-
git@github.com:apache/rocketmq.git
scm:git:git@github.com:apache/rocketmq.git
@@ -106,7 +102,6 @@
${project.basedir}/../test/target/jacoco-it.exec
file:**/generated-sources/**,**/test/**
- 2.0.2
@@ -119,7 +114,6 @@
namesrv
remoting
logappender
- example
srvutil
filter
test
@@ -127,6 +121,7 @@
openmessaging
logging
acl
+ example
@@ -182,21 +177,6 @@
true
-
- maven-javadoc-plugin
- 2.10.4
-
- UTF-8
-
-
-
- attach-javadocs
-
- jar
-
-
-
-
maven-source-plugin
3.0.1
@@ -444,7 +424,7 @@
junit
junit
- 4.11
+ 4.13.2
test
@@ -456,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
@@ -532,12 +506,17 @@
${project.groupId}
- rocketmq-example
+ rocketmq-acl
${project.version}
${project.groupId}
- rocketmq-acl
+ rocketmq-openmessaging
+ ${project.version}
+
+
+ ${project.groupId}
+ rocketmq-example
${project.version}
@@ -550,11 +529,6 @@
logback-classic
1.0.13
-
- ch.qos.logback
- logback-core
- 1.0.13
-
commons-cli
commons-cli
@@ -568,7 +542,7 @@
com.alibaba
fastjson
- 1.2.68
+ 1.2.76
org.javassist
@@ -623,7 +597,7 @@
commons-validator
commons-validator
- 1.6
+ 1.7
diff --git a/remoting/pom.xml b/remoting/pom.xml
index d71f0364a67b89a52e518cfc49bed8f23d02f5af..765e1a93bc0f83a7d59a794619ba356f7cccda9c 100644
--- a/remoting/pom.xml
+++ b/remoting/pom.xml
@@ -19,7 +19,7 @@
org.apache.rocketmq
rocketmq-all
- 4.7.1-SNAPSHOT
+ 4.9.1-SNAPSHOT
4.0.0
@@ -27,11 +27,6 @@
rocketmq-remoting
rocketmq-remoting ${project.version}
-
- 1.6
- 1.6
-
-
com.alibaba
@@ -45,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 a16940e561c5cec23c9df021c429e1c64d500b88..d936c3bf696ab0399a323ea028e9ee12ee46ce5a 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 d836c8e0bfba9865215144279ba3ecba040d2b0d..5ba6cfab0a740a46a20d69a104b74094ad81993f 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 efbdd52c07387327e5d10bdca8be006c7ef677d1..5003ce39efb03b5a8c75a88d1bd90a33921ee5ff 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 5330c90060da4304d3bba550cdfe2f5415474153..a272d21da41b3c41d58755eccde5f4bf64980fdd 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 6b5633df1d74a33c87dbceb3df270b2f1c580224..4b38ce9524c4b6e20a6e365c9541d7f922dfb186 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 60090978628a8f65ab2a2ddb72249994f904e7a3..9c4544c0b25e55c1e817aba7c49f2574d0dd0dc6 100644
--- a/srvutil/pom.xml
+++ b/srvutil/pom.xml
@@ -19,7 +19,7 @@
org.apache.rocketmq
rocketmq-all
- 4.7.1-SNAPSHOT
+ 4.9.1-SNAPSHOT
4.0.0
diff --git a/store/pom.xml b/store/pom.xml
index 59a9bfa8f22736ea2832fbdbfb3fba7e58807dfc..23e9763d81402d43340a3db26bf29a654b7e9587 100644
--- a/store/pom.xml
+++ b/store/pom.xml
@@ -19,7 +19,7 @@
org.apache.rocketmq
rocketmq-all
- 4.7.1-SNAPSHOT
+ 4.9.1-SNAPSHOT
4.0.0
@@ -31,7 +31,7 @@
io.openmessaging.storage
dledger
- 0.1
+ 0.2.2
org.apache.rocketmq
@@ -56,10 +56,5 @@
logback-classic
test
-
- ch.qos.logback
- logback-core
- test
-
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 810110eeb67237342e6005e46fdc29b8e3f6c65f..cce6481b8daa119def971b3c4c2f95d4b3e6502a 100644
--- a/store/src/main/java/org/apache/rocketmq/store/CommitLog.java
+++ b/store/src/main/java/org/apache/rocketmq/store/CommitLog.java
@@ -37,6 +37,7 @@ 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.common.sysflag.MessageSysFlag;
+import org.apache.rocketmq.common.topic.TopicValidator;
import org.apache.rocketmq.logging.InternalLogger;
import org.apache.rocketmq.logging.InternalLoggerFactory;
import org.apache.rocketmq.store.config.BrokerRole;
@@ -340,7 +341,7 @@ public class CommitLog {
// Timing message processing
{
String t = propertiesMap.get(MessageConst.PROPERTY_DELAY_TIME_LEVEL);
- if (ScheduleMessageService.SCHEDULE_TOPIC.equals(topic) && t != null) {
+ if (TopicValidator.RMQ_SYS_SCHEDULE_TOPIC.equals(topic) && t != null) {
int delayLevel = Integer.parseInt(t);
if (delayLevel > this.defaultMessageStore.getScheduleMessageService().getMaxDelayLevel()) {
@@ -577,7 +578,7 @@ public class CommitLog {
msg.setDelayTimeLevel(this.defaultMessageStore.getScheduleMessageService().getMaxDelayLevel());
}
- topic = ScheduleMessageService.SCHEDULE_TOPIC;
+ topic = TopicValidator.RMQ_SYS_SCHEDULE_TOPIC;
queueId = ScheduleMessageService.delayLevel2QueueId(msg.getDelayTimeLevel());
// Backup real topic, queueId
@@ -660,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;
});
@@ -761,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;
});
@@ -799,7 +807,7 @@ public class CommitLog {
msg.setDelayTimeLevel(this.defaultMessageStore.getScheduleMessageService().getMaxDelayLevel());
}
- topic = ScheduleMessageService.SCHEDULE_TOPIC;
+ topic = TopicValidator.RMQ_SYS_SCHEDULE_TOPIC;
queueId = ScheduleMessageService.delayLevel2QueueId(msg.getDelayTimeLevel());
// Backup real topic, queueId
@@ -899,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;
@@ -925,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()) {
@@ -1419,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);
@@ -1794,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();
@@ -1817,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) {
@@ -1870,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 900e9af31fa5d51c8342be4ee8cffa23df49e822..b8ecdee8cc63141876bf6b8f0b2efb3f811479b1 100644
--- a/store/src/main/java/org/apache/rocketmq/store/DefaultMessageStore.java
+++ b/store/src/main/java/org/apache/rocketmq/store/DefaultMessageStore.java
@@ -50,6 +50,7 @@ import org.apache.rocketmq.common.message.MessageExt;
import org.apache.rocketmq.common.message.MessageExtBatch;
import org.apache.rocketmq.common.running.RunningStats;
import org.apache.rocketmq.common.sysflag.MessageSysFlag;
+import org.apache.rocketmq.common.topic.TopicValidator;
import org.apache.rocketmq.logging.InternalLogger;
import org.apache.rocketmq.logging.InternalLoggerFactory;
import org.apache.rocketmq.store.config.BrokerRole;
@@ -391,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;
}
@@ -399,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 {
@@ -803,13 +805,22 @@ public class DefaultMessageStore implements MessageStore {
return this.storeStatsService.toString();
}
+ private String getStorePathPhysic() {
+ String storePathPhysic = "";
+ if (DefaultMessageStore.this.getMessageStoreConfig().isEnableDLegerCommitLog()) {
+ storePathPhysic = ((DLedgerCommitLog)DefaultMessageStore.this.getCommitLog()).getdLedgerServer().getdLedgerConfig().getDataStorePath();
+ } else {
+ storePathPhysic = DefaultMessageStore.this.getMessageStoreConfig().getStorePathCommitLog();
+ }
+ return storePathPhysic;
+ }
+
@Override
public HashMap getRuntimeInfo() {
HashMap result = this.storeStatsService.getRuntimeInfo();
{
- String storePathPhysic = DefaultMessageStore.this.getMessageStoreConfig().getStorePathCommitLog();
- double physicRatio = UtilAll.getDiskPartitionSpaceUsedPercent(storePathPhysic);
+ double physicRatio = UtilAll.getDiskPartitionSpaceUsedPercent(getStorePathPhysic());
result.put(RunningStats.commitLogDiskRatio.name(), String.valueOf(physicRatio));
}
@@ -1019,7 +1030,8 @@ public class DefaultMessageStore implements MessageStore {
Entry> next = it.next();
String topic = next.getKey();
- if (!topics.contains(topic) && !topic.equals(ScheduleMessageService.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();
@@ -1050,7 +1062,7 @@ public class DefaultMessageStore implements MessageStore {
while (it.hasNext()) {
Entry> next = it.next();
String topic = next.getKey();
- if (!topic.equals(ScheduleMessageService.SCHEDULE_TOPIC)) {
+ if (!topic.equals(TopicValidator.RMQ_SYS_SCHEDULE_TOPIC)) {
ConcurrentMap queueTable = next.getValue();
Iterator> itQT = queueTable.entrySet().iterator();
while (itQT.hasNext()) {
@@ -1675,8 +1687,7 @@ public class DefaultMessageStore implements MessageStore {
cleanImmediately = false;
{
- String storePathPhysic = DefaultMessageStore.this.getMessageStoreConfig().getStorePathCommitLog();
- double physicRatio = UtilAll.getDiskPartitionSpaceUsedPercent(storePathPhysic);
+ double physicRatio = UtilAll.getDiskPartitionSpaceUsedPercent(getStorePathPhysic());
if (physicRatio > diskSpaceWarningLevelRatio) {
boolean diskok = DefaultMessageStore.this.runningFlags.getAndMakeDiskFull();
if (diskok) {
@@ -1736,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);
@@ -1937,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 9185d21d874dce268c937321c2a19ca2a10790eb..b5bdc7766b118f02b7f6c152b85f509ca03e8644 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/config/MessageStoreConfig.java b/store/src/main/java/org/apache/rocketmq/store/config/MessageStoreConfig.java
index 7891f71067a26e4118efde7c79a0b7de7279b8be..848fe22decdb211064003ae1e7c6b7cf832da55d 100644
--- a/store/src/main/java/org/apache/rocketmq/store/config/MessageStoreConfig.java
+++ b/store/src/main/java/org/apache/rocketmq/store/config/MessageStoreConfig.java
@@ -54,13 +54,12 @@ public class MessageStoreConfig {
/**
* introduced since 4.0.x. Determine whether to use mutex reentrantLock when putting message.
- * By default it is set to false indicating using spin lock when putting message.
*/
- private boolean useReentrantLockWhenPutMessage = false;
+ private boolean useReentrantLockWhenPutMessage = true;
- // Whether schedule flush,default is real-time
+ // Whether schedule flush
@ImportantField
- private boolean flushCommitLogTimed = false;
+ private boolean flushCommitLogTimed = true;
// ConsumeQueue flush interval
private int flushIntervalConsumeQueue = 1000;
// Resource reclaim interval
@@ -148,6 +147,12 @@ public class MessageStoreConfig {
private String dLegerPeers;
private String dLegerSelfId;
+ private String preferredLeaderId;
+
+ private boolean isEnableBatchPush = false;
+
+ private boolean enableScheduleMessageStats = true;
+
public boolean isDebugLockEnable() {
return debugLockEnable;
}
@@ -702,4 +707,28 @@ public class MessageStoreConfig {
public void setEnableDLegerCommitLog(boolean enableDLegerCommitLog) {
this.enableDLegerCommitLog = enableDLegerCommitLog;
}
+
+ public String getPreferredLeaderId() {
+ return preferredLeaderId;
+ }
+
+ public void setPreferredLeaderId(String preferredLeaderId) {
+ this.preferredLeaderId = preferredLeaderId;
+ }
+
+ public boolean isEnableBatchPush() {
+ return isEnableBatchPush;
+ }
+
+ public void setEnableBatchPush(boolean enableBatchPush) {
+ isEnableBatchPush = enableBatchPush;
+ }
+
+ public boolean isEnableScheduleMessageStats() {
+ return enableScheduleMessageStats;
+ }
+
+ public void setEnableScheduleMessageStats(boolean enableScheduleMessageStats) {
+ this.enableScheduleMessageStats = enableScheduleMessageStats;
+ }
}
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 3d748bf8900b5c92ae35cc8b9513109519ce8a86..90fd6f3f169871fa1d6a226b08a6d0a6a8a901f4 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;
@@ -38,6 +44,7 @@ import org.apache.rocketmq.common.message.MessageConst;
import org.apache.rocketmq.common.message.MessageDecoder;
import org.apache.rocketmq.common.message.MessageExtBatch;
import org.apache.rocketmq.common.sysflag.MessageSysFlag;
+import org.apache.rocketmq.common.topic.TopicValidator;
import org.apache.rocketmq.store.AppendMessageResult;
import org.apache.rocketmq.store.AppendMessageStatus;
import org.apache.rocketmq.store.CommitLog;
@@ -71,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();
@@ -83,6 +92,9 @@ public class DLedgerCommitLog extends CommitLog {
dLedgerConfig.setMappedFileSizeForEntryData(defaultMessageStore.getMessageStoreConfig().getMappedFileSizeCommitLog());
dLedgerConfig.setDeleteWhen(defaultMessageStore.getMessageStoreConfig().getDeleteWhen());
dLedgerConfig.setFileReservedHours(defaultMessageStore.getMessageStoreConfig().getFileReservedTime() + 1);
+ dLedgerConfig.setPreferredLeaderId(defaultMessageStore.getMessageStoreConfig().getPreferredLeaderId());
+ dLedgerConfig.setEnableBatchPush(defaultMessageStore.getMessageStoreConfig().isEnableBatchPush());
+
id = Integer.valueOf(dLedgerConfig.getSelfId().substring(1)) + 1;
dLedgerServer = new DLedgerServer(dLedgerConfig);
dLedgerFileStore = (DLedgerMmapFileStore) dLedgerServer.getdLedgerStore();
@@ -360,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
@@ -383,8 +388,9 @@ public class DLedgerCommitLog extends CommitLog {
msg.setDelayTimeLevel(this.defaultMessageStore.getScheduleMessageService().getMaxDelayLevel());
}
- topic = ScheduleMessageService.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());
@@ -396,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));
@@ -426,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:
@@ -487,17 +514,354 @@ 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;
+ int 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);
+ appendResult.setMsgNum(msgNum);
+ 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;
+ int 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);
+ appendResult.setMsgNum(msgNum);
+ 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
@@ -562,51 +926,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;
@@ -614,33 +1010,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
@@ -662,6 +1032,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
@@ -671,60 +1043,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);
+ }
+ 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);
}
- 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, key, batchBody, totalMsgLen);
}
private void resetByteBuffer(final ByteBuffer byteBuffer, final int limit) {
byteBuffer.flip();
byteBuffer.limit(limit);
}
-
}
public static class DLedgerSelectMappedBufferResult extends SelectMappedBufferResult {
@@ -736,6 +1211,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 a0e77fa3dc96ea0b5b23a405a2f0f05701d5b41d..34c51eb9e26fc5df4efbc8bef58d360f759a5fe5 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/main/java/org/apache/rocketmq/store/schedule/ScheduleMessageService.java b/store/src/main/java/org/apache/rocketmq/store/schedule/ScheduleMessageService.java
index 3be8cbc809ed59f6d39de94cd407a01741a899be..bacae1e80bcfb6d7455a88ed493efb270cd595d1 100644
--- a/store/src/main/java/org/apache/rocketmq/store/schedule/ScheduleMessageService.java
+++ b/store/src/main/java/org/apache/rocketmq/store/schedule/ScheduleMessageService.java
@@ -25,9 +25,9 @@ import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicBoolean;
import org.apache.rocketmq.common.ConfigManager;
-import org.apache.rocketmq.common.MixAll;
import org.apache.rocketmq.common.TopicFilterType;
import org.apache.rocketmq.common.constant.LoggerName;
+import org.apache.rocketmq.common.topic.TopicValidator;
import org.apache.rocketmq.logging.InternalLogger;
import org.apache.rocketmq.logging.InternalLoggerFactory;
import org.apache.rocketmq.common.message.MessageAccessor;
@@ -48,7 +48,6 @@ import org.apache.rocketmq.store.config.StorePathConfigHelper;
public class ScheduleMessageService extends ConfigManager {
private static final InternalLogger log = InternalLoggerFactory.getLogger(LoggerName.STORE_LOGGER_NAME);
- public static final String SCHEDULE_TOPIC = "SCHEDULE_TOPIC_XXXX";
private static final long FIRST_DELAY_TIME = 1000L;
private static final long DELAY_FOR_A_WHILE = 100L;
private static final long DELAY_FOR_A_PERIOD = 10000L;
@@ -91,7 +90,7 @@ public class ScheduleMessageService extends ConfigManager {
Map.Entry next = it.next();
int queueId = delayLevel2QueueId(next.getKey());
long delayOffset = next.getValue();
- long maxOffset = this.defaultMessageStore.getMaxOffsetInQueue(SCHEDULE_TOPIC, queueId);
+ long maxOffset = this.defaultMessageStore.getMaxOffsetInQueue(TopicValidator.RMQ_SYS_SCHEDULE_TOPIC, queueId);
String value = String.format("%d,%d", delayOffset, maxOffset);
String key = String.format("%s_%d", RunningStats.scheduleMessageOffset.name(), next.getKey());
stats.put(key, value);
@@ -113,6 +112,7 @@ public class ScheduleMessageService extends ConfigManager {
public void start() {
if (started.compareAndSet(false, true)) {
+ super.load();
this.timer = new Timer("ScheduleMessageTimerThread", true);
for (Map.Entry entry : this.delayLevelTable.entrySet()) {
Integer level = entry.getKey();
@@ -262,7 +262,7 @@ public class ScheduleMessageService extends ConfigManager {
public void executeOnTimeup() {
ConsumeQueue cq =
- ScheduleMessageService.this.defaultMessageStore.findConsumeQueue(SCHEDULE_TOPIC,
+ ScheduleMessageService.this.defaultMessageStore.findConsumeQueue(TopicValidator.RMQ_SYS_SCHEDULE_TOPIC,
delayLevel2QueueId(delayLevel));
long failScheduleOffset = offset;
@@ -306,7 +306,7 @@ public class ScheduleMessageService extends ConfigManager {
if (msgExt != null) {
try {
MessageExtBrokerInner msgInner = this.messageTimeup(msgExt);
- if (MixAll.RMQ_SYS_TRANS_HALF_TOPIC.equals(msgInner.getTopic())) {
+ if (TopicValidator.RMQ_SYS_TRANS_HALF_TOPIC.equals(msgInner.getTopic())) {
log.error("[BUG] the real topic of schedule msg is {}, discard the msg. msg={}",
msgInner.getTopic(), msgInner);
continue;
@@ -317,6 +317,12 @@ public class ScheduleMessageService extends ConfigManager {
if (putMessageResult != null
&& putMessageResult.getPutMessageStatus() == PutMessageStatus.PUT_OK) {
+ if (ScheduleMessageService.this.defaultMessageStore.getMessageStoreConfig().isEnableScheduleMessageStats()) {
+ ScheduleMessageService.this.defaultMessageStore.getBrokerStatsManager().incTopicPutNums(msgInner.getTopic(), putMessageResult.getAppendMessageResult().getMsgNum(), 1);
+ ScheduleMessageService.this.defaultMessageStore.getBrokerStatsManager().incTopicPutSize(msgInner.getTopic(),
+ putMessageResult.getAppendMessageResult().getWroteBytes());
+ ScheduleMessageService.this.defaultMessageStore.getBrokerStatsManager().incBrokerPutNums(putMessageResult.getAppendMessageResult().getMsgNum());
+ }
continue;
} else {
// XXX: warn and notify me
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 8618dbb0e56ed2804303d1b08bbe94cc5e54f500..b3a7c196f94996e3d967d2efaad89a416f3eeaaa 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 e43bb4bc3d3f84ab382fee0adb492082c37a8222..db7d367e02135cdb577a4f97624cf93cfd69be22 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 fd13e71a427d07db60400392a8718bcc64de0298..440f9146314a049a91e7096f4b382399b878f8d6 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 a736754de47b4ce6d699b63360dfebf1eb86ee0d..5660de1363d71da69d7ceaf088cc2210df8a3655 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 f0b9205302e965a832393d788d122e64bbb5d0aa..8ab8a23b4715ec4ff0742b2f5b0df4a6239c9f02 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,93 @@ 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());
+ 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 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());
@@ -175,15 +264,60 @@ public class DLedgerCommitlogTest extends MessageStoreTestBase {
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/store/src/test/java/org/apache/rocketmq/store/dledger/MessageStoreTestBase.java b/store/src/test/java/org/apache/rocketmq/store/dledger/MessageStoreTestBase.java
index 5b0ca347579dc7e391dab25645d5a87620a89269..5864b282c7bbff80bc4ca7a2e4db54541ace3bbd 100644
--- a/store/src/test/java/org/apache/rocketmq/store/dledger/MessageStoreTestBase.java
+++ b/store/src/test/java/org/apache/rocketmq/store/dledger/MessageStoreTestBase.java
@@ -63,9 +63,9 @@ public class MessageStoreTestBase extends StoreTestBase {
if (leaderId != null) {
dLegerServer.getdLedgerConfig().setEnableLeaderElector(false);
if (selfId.equals(leaderId)) {
- dLegerServer.getMemberState().changeToLeader(-1);
+ dLegerServer.getMemberState().changeToLeader(0);
} else {
- dLegerServer.getMemberState().changeToFollower(-1, leaderId);
+ dLegerServer.getMemberState().changeToFollower(0, leaderId);
}
}
diff --git a/store/src/test/java/org/apache/rocketmq/store/schedule/ScheduleMessageServiceTest.java b/store/src/test/java/org/apache/rocketmq/store/schedule/ScheduleMessageServiceTest.java
index fd860e6b9d7ea5d8a3d2c6e3a4fee714cda35d57..fa3c6bfcd8b9fd08035d5c7c409a10337f32b8d0 100644
--- a/store/src/test/java/org/apache/rocketmq/store/schedule/ScheduleMessageServiceTest.java
+++ b/store/src/test/java/org/apache/rocketmq/store/schedule/ScheduleMessageServiceTest.java
@@ -40,6 +40,9 @@ import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
+import static org.apache.rocketmq.store.stats.BrokerStatsManager.BROKER_PUT_NUMS;
+import static org.apache.rocketmq.store.stats.BrokerStatsManager.TOPIC_PUT_NUMS;
+import static org.apache.rocketmq.store.stats.BrokerStatsManager.TOPIC_PUT_SIZE;
import static org.assertj.core.api.Assertions.assertThat;
@@ -112,6 +115,10 @@ public class ScheduleMessageServiceTest {
@Test
public void deliverDelayedMessageTimerTaskTest() throws Exception {
+ assertThat(messageStore.getMessageStoreConfig().isEnableScheduleMessageStats()).isTrue();
+
+ assertThat(messageStore.getBrokerStatsManager().getStatsItem(TOPIC_PUT_NUMS, topic)).isNull();
+
MessageExtBrokerInner msg = buildMessage();
int realQueueId = msg.getQueueId();
// set delayLevel,and send delay message
@@ -141,6 +148,10 @@ public class ScheduleMessageServiceTest {
// now,found the message
assertThat(messageResult.getStatus()).isEqualTo(GetMessageStatus.FOUND);
+ // get the stats change
+ assertThat(messageStore.getBrokerStatsManager().getStatsItem(BROKER_PUT_NUMS, brokerConfig.getBrokerClusterName()).getValue().get()).isEqualTo(1);
+ assertThat(messageStore.getBrokerStatsManager().getStatsItem(TOPIC_PUT_NUMS, topic).getValue().get()).isEqualTo(1L);
+ assertThat(messageStore.getBrokerStatsManager().getStatsItem(TOPIC_PUT_SIZE, topic).getValue().get()).isEqualTo(messageResult.getBufferTotalSize());
// get the message body
ByteBuffer byteBuffer = ByteBuffer.allocate(messageResult.getBufferTotalSize());
diff --git a/test/pom.xml b/test/pom.xml
index ce9a8a9a7dff4240fc52019d3453e12937799808..41296501c28b649e170660c8490325641be836ce 100644
--- a/test/pom.xml
+++ b/test/pom.xml
@@ -20,7 +20,7 @@
rocketmq-all
org.apache.rocketmq
- 4.7.1-SNAPSHOT
+ 4.9.1-SNAPSHOT
4.0.0
@@ -31,7 +31,6 @@
log4j
log4j
- 1.2.17
${project.groupId}
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 44db782b5c53b82ece5db8fba626071f6f8407fb..e08967eb91de53826980b94f530c3e2ff299ae6c 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 6edeecadb2a2d2ec19b55a14801f49bf0321409b..0c24427d9248788a4db636a14d114d6ff1f66196 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 1c2bdac305781e3923bdb3bc334f03548f26639c..41cacb684c3c175fa8316a3e2ce10dc2dd546389 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 9eca28bbe7d90c8e0bf5f9e15525ce943735c9b8..3f71176d6f01db16000a49cf6fc47e5c6e57ce9c 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 965d2ee6705c467d7cde0bdcd77c06a57c814fff..69bfd8f7d10ed5a07b24621cab801819f3805697 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 82ab461aa53607c475f1aff7f6adda1118be728f..bdd991a335fcd170da3c604dfa1101c5c326ee86 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 564da5ceaf1cf701ea91639f6fb780de126bc76b..0edbdbe2e386c2bea5029ce571387ec794a22315 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 31321975b57b9c2c0e52096a9d0a6bd113b4ed0f..8de1b7d4e0110919151ae7d0d567aeb430fad5ff 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 3031095e70521e65a472f18c392d957e3981d35a..7840ab78c110eb870b06b901b75d2094027a1444 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 c6938afdb7e188a6b4a5a6a76619aea090eddbc0..abe8197de3974b6c3b1f52f9e5efbbf5078224dd 100644
--- a/tools/pom.xml
+++ b/tools/pom.xml
@@ -19,7 +19,7 @@
org.apache.rocketmq
rocketmq-all
- 4.7.1-SNAPSHOT
+ 4.9.1-SNAPSHOT
4.0.0
@@ -56,10 +56,6 @@
ch.qos.logback
logback-classic
-
- ch.qos.logback
- logback-core
-
org.apache.commons
commons-lang3
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 1ca3fe4c2f482a286b485021544d74dca16d39bf..6592639035f922a362f7503342d34f7ff06ac11b 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
@@ -26,7 +26,6 @@ import org.apache.rocketmq.client.QueryResult;
import org.apache.rocketmq.client.exception.MQBrokerException;
import org.apache.rocketmq.client.exception.MQClientException;
import org.apache.rocketmq.common.AclConfig;
-import org.apache.rocketmq.common.MixAll;
import org.apache.rocketmq.common.PlainAccessConfig;
import org.apache.rocketmq.common.TopicConfig;
import org.apache.rocketmq.common.admin.ConsumeStats;
@@ -51,6 +50,7 @@ import org.apache.rocketmq.common.protocol.body.TopicConfigSerializeWrapper;
import org.apache.rocketmq.common.protocol.body.TopicList;
import org.apache.rocketmq.common.protocol.route.TopicRouteData;
import org.apache.rocketmq.common.subscription.SubscriptionGroupConfig;
+import org.apache.rocketmq.common.topic.TopicValidator;
import org.apache.rocketmq.remoting.RPCHook;
import org.apache.rocketmq.remoting.exception.RemotingCommandException;
import org.apache.rocketmq.remoting.exception.RemotingConnectException;
@@ -62,7 +62,7 @@ import org.apache.rocketmq.tools.admin.api.MessageTrack;
public class DefaultMQAdminExt extends ClientConfig implements MQAdminExt {
private final DefaultMQAdminExtImpl defaultMQAdminExtImpl;
private String adminExtGroup = "admin_ext_group";
- private String createTopicKey = MixAll.AUTO_CREATE_TOPIC_KEY_TOPIC;
+ private String createTopicKey = TopicValidator.AUTO_CREATE_TOPIC_KEY_TOPIC;
private long timeoutMillis = 5000;
public DefaultMQAdminExt() {
@@ -128,12 +128,18 @@ public class DefaultMQAdminExt extends ClientConfig implements MQAdminExt {
}
@Override
- public QueryResult queryMessage(String topic, String key, int maxNum, long begin,
- long end) throws MQClientException,
- InterruptedException {
+ public QueryResult queryMessage(String topic, String key, int maxNum, long begin, long end)
+ throws MQClientException, InterruptedException {
+
return defaultMQAdminExtImpl.queryMessage(topic, key, maxNum, begin, end);
}
+ public QueryResult queryMessageByUniqKey(String topic, String key, int maxNum, long begin, long end)
+ throws MQClientException, InterruptedException {
+
+ return defaultMQAdminExtImpl.queryMessageByUniqKey(topic, key, maxNum, begin, end);
+ }
+
@Override
public void start() throws MQClientException {
defaultMQAdminExtImpl.start();
@@ -320,6 +326,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 22d4005ce9a9e031c0b10e1d09ae6b1a471cc65c..8930bbe49d207ab2dc361caaee6d88f75762cbea 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
@@ -991,12 +998,18 @@ public class DefaultMQAdminExtImpl implements MQAdminExt, MQAdminExtInner {
}
@Override
- public QueryResult queryMessage(String topic, String key, int maxNum, long begin,
- long end) throws MQClientException,
- InterruptedException {
+ public QueryResult queryMessage(String topic, String key, int maxNum, long begin, long end)
+ throws MQClientException, InterruptedException {
+
return this.mqClientInstance.getMQAdminImpl().queryMessage(topic, key, maxNum, begin, end);
}
+ public QueryResult queryMessageByUniqKey(String topic, String key, int maxNum, long begin,
+ long end) throws MQClientException, InterruptedException {
+
+ return this.mqClientInstance.getMQAdminImpl().queryMessageByUniqKey(topic, key, maxNum, begin, end);
+ }
+
@Override
public void updateConsumeOffset(String brokerAddr, String consumeGroup, MessageQueue mq,
long offset) throws RemotingException, InterruptedException, MQBrokerException {
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 17b62251c60d5af461db085bb8587fbcf9f14f4f..d5462cb04e5a41873690c10cf67b880e21ad6bd1 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/MQAdminStartup.java b/tools/src/main/java/org/apache/rocketmq/tools/command/MQAdminStartup.java
index 28431a963ee676ea5acef4c9ebd0ee8b9e0e2f2e..f9477445bea3d895dd9f52a0c7f7a1127ee95d67 100644
--- a/tools/src/main/java/org/apache/rocketmq/tools/command/MQAdminStartup.java
+++ b/tools/src/main/java/org/apache/rocketmq/tools/command/MQAdminStartup.java
@@ -59,6 +59,7 @@ import org.apache.rocketmq.tools.command.message.QueryMsgByIdSubCommand;
import org.apache.rocketmq.tools.command.message.QueryMsgByKeySubCommand;
import org.apache.rocketmq.tools.command.message.QueryMsgByOffsetSubCommand;
import org.apache.rocketmq.tools.command.message.QueryMsgByUniqueKeySubCommand;
+import org.apache.rocketmq.tools.command.message.QueryMsgTraceByIdSubCommand;
import org.apache.rocketmq.tools.command.message.SendMessageCommand;
import org.apache.rocketmq.tools.command.namesrv.DeleteKvConfigCommand;
import org.apache.rocketmq.tools.command.namesrv.GetNamesrvConfigCommand;
@@ -164,6 +165,7 @@ public class MQAdminStartup {
initCommand(new QueryMsgByKeySubCommand());
initCommand(new QueryMsgByUniqueKeySubCommand());
initCommand(new QueryMsgByOffsetSubCommand());
+ initCommand(new QueryMsgTraceByIdSubCommand());
initCommand(new PrintMessageSubCommand());
initCommand(new PrintMessageByQueueCommand());
diff --git a/tools/src/main/java/org/apache/rocketmq/tools/command/broker/GetBrokerConfigCommand.java b/tools/src/main/java/org/apache/rocketmq/tools/command/broker/GetBrokerConfigCommand.java
index 11a36048328f4e40ebcfc0decb3092cd19f4238c..11346bf6f7f18f132913aab90b959f3c0a21a3bf 100644
--- a/tools/src/main/java/org/apache/rocketmq/tools/command/broker/GetBrokerConfigCommand.java
+++ b/tools/src/main/java/org/apache/rocketmq/tools/command/broker/GetBrokerConfigCommand.java
@@ -48,11 +48,11 @@ public class GetBrokerConfigCommand implements SubCommand {
@Override
public Options buildCommandlineOptions(final Options options) {
- Option opt = new Option("b", "brokerAddr", true, "update which broker");
+ Option opt = new Option("b", "brokerAddr", true, "get which broker");
opt.setRequired(false);
options.addOption(opt);
- opt = new Option("c", "clusterName", true, "update which cluster");
+ opt = new Option("c", "clusterName", true, "get which cluster");
opt.setRequired(false);
options.addOption(opt);
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 5038123561bf0aafb880ee0100d3e3323c2c49ae..872a130d9f52ccafd240b49c3b32850e2b56f505 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 b946ee141ebc507da3df465b9a9fa31c043790a7..7985f9d5918cd918e52d84f0f954d04709158c83 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 96d81956e4540e4574a027ebf9a88ffd16284431..fb0efebaa215445a52c016f5a90abb5cf06e56db 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/message/QueryMsgByUniqueKeySubCommand.java b/tools/src/main/java/org/apache/rocketmq/tools/command/message/QueryMsgByUniqueKeySubCommand.java
index 9ad075082f667823e779c7a5413a0bc9d0e2171e..8c7bec616d7068a8fab2c8c03d79cabcfb1e64cb 100644
--- a/tools/src/main/java/org/apache/rocketmq/tools/command/message/QueryMsgByUniqueKeySubCommand.java
+++ b/tools/src/main/java/org/apache/rocketmq/tools/command/message/QueryMsgByUniqueKeySubCommand.java
@@ -24,6 +24,7 @@ import java.util.List;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.Option;
import org.apache.commons.cli.Options;
+import org.apache.rocketmq.client.QueryResult;
import org.apache.rocketmq.client.exception.MQBrokerException;
import org.apache.rocketmq.client.exception.MQClientException;
import org.apache.rocketmq.common.UtilAll;
@@ -57,82 +58,43 @@ public class QueryMsgByUniqueKeySubCommand implements SubCommand {
}
}
- public static void queryById(final DefaultMQAdminExt admin, final String topic,
- final String msgId) throws MQClientException,
- RemotingException, MQBrokerException, InterruptedException, IOException {
- MessageExt msg = admin.viewMessage(topic, msgId);
-
- String bodyTmpFilePath = createBodyFile(msg);
-
- System.out.printf("%-20s %s%n",
- "Topic:",
- msg.getTopic()
- );
-
- System.out.printf("%-20s %s%n",
- "Tags:",
- "[" + msg.getTags() + "]"
- );
-
- System.out.printf("%-20s %s%n",
- "Keys:",
- "[" + msg.getKeys() + "]"
- );
-
- System.out.printf("%-20s %d%n",
- "Queue ID:",
- msg.getQueueId()
- );
-
- System.out.printf("%-20s %d%n",
- "Queue Offset:",
- msg.getQueueOffset()
- );
-
- System.out.printf("%-20s %d%n",
- "CommitLog Offset:",
- msg.getCommitLogOffset()
- );
-
- System.out.printf("%-20s %d%n",
- "Reconsume Times:",
- msg.getReconsumeTimes()
- );
-
- System.out.printf("%-20s %s%n",
- "Born Timestamp:",
- UtilAll.timeMillisToHumanString2(msg.getBornTimestamp())
- );
-
- System.out.printf("%-20s %s%n",
- "Store Timestamp:",
- UtilAll.timeMillisToHumanString2(msg.getStoreTimestamp())
- );
-
- System.out.printf("%-20s %s%n",
- "Born Host:",
- RemotingHelper.parseSocketAddressAddr(msg.getBornHost())
- );
-
- System.out.printf("%-20s %s%n",
- "Store Host:",
- RemotingHelper.parseSocketAddressAddr(msg.getStoreHost())
- );
-
- System.out.printf("%-20s %d%n",
- "System Flag:",
- msg.getSysFlag()
- );
-
- System.out.printf("%-20s %s%n",
- "Properties:",
- msg.getProperties() != null ? msg.getProperties().toString() : ""
- );
-
- System.out.printf("%-20s %s%n",
- "Message Body Path:",
- bodyTmpFilePath
- );
+ public static void queryById(final DefaultMQAdminExt admin, final String topic, final String msgId,
+ final boolean showAll) throws MQClientException,
+ RemotingException, MQBrokerException, InterruptedException, IOException {
+
+ QueryResult queryResult = admin.queryMessageByUniqKey(topic, msgId, 32, 0, Long.MAX_VALUE);
+ assert queryResult != null;
+ List list = queryResult.getMessageList();
+ if (list == null || list.size() == 0) {
+ return;
+ }
+ list.sort((o1, o2) -> (int) (o1.getStoreTimestamp() - o2.getStoreTimestamp()));
+ for (int i = 0; i < (showAll ? list.size() : 1); i++) {
+ showMessage(admin, list.get(i), i);
+ }
+ }
+
+ private static void showMessage(final DefaultMQAdminExt admin, MessageExt msg, int index) throws IOException {
+ String bodyTmpFilePath = createBodyFile(msg, index);
+
+ final String strFormat = "%-20s %s%n";
+ final String intFormat = "%-20s %d%n";
+
+ System.out.printf(strFormat, "Topic:", msg.getTopic());
+ System.out.printf(strFormat, "Tags:", "[" + msg.getTags() + "]");
+ System.out.printf(strFormat, "Keys:", "[" + msg.getKeys() + "]");
+ System.out.printf(intFormat, "Queue ID:", msg.getQueueId());
+ System.out.printf(intFormat, "Queue Offset:", msg.getQueueOffset());
+ System.out.printf(intFormat, "CommitLog Offset:", msg.getCommitLogOffset());
+ System.out.printf(intFormat, "Reconsume Times:", msg.getReconsumeTimes());
+ System.out.printf(strFormat, "Born Timestamp:", UtilAll.timeMillisToHumanString2(msg.getBornTimestamp()));
+ System.out.printf(strFormat, "Store Timestamp:", UtilAll.timeMillisToHumanString2(msg.getStoreTimestamp()));
+ System.out.printf(strFormat, "Born Host:", RemotingHelper.parseSocketAddressAddr(msg.getBornHost()));
+ System.out.printf(strFormat, "Store Host:", RemotingHelper.parseSocketAddressAddr(msg.getStoreHost()));
+ System.out.printf(intFormat, "System Flag:", msg.getSysFlag());
+ System.out.printf(strFormat, "Properties:",
+ msg.getProperties() != null ? msg.getProperties().toString() : "");
+ System.out.printf(strFormat, "Message Body Path:", bodyTmpFilePath);
try {
List mtdList = admin.messageTrackDetail(msg);
@@ -149,18 +111,21 @@ public class QueryMsgByUniqueKeySubCommand implements SubCommand {
}
}
- private static String createBodyFile(MessageExt msg) throws IOException {
+ private static String createBodyFile(MessageExt msg, int index) throws IOException {
DataOutputStream dos = null;
try {
- String bodyTmpFilePath = "/tmp/rocketmq/msgbodys";
- File file = new File(bodyTmpFilePath);
+ StringBuffer bodyTmpFilePath = new StringBuffer("/tmp/rocketmq/msgbodys");
+ File file = new File(bodyTmpFilePath.toString());
if (!file.exists()) {
file.mkdirs();
}
- bodyTmpFilePath = bodyTmpFilePath + "/" + msg.getMsgId();
- dos = new DataOutputStream(new FileOutputStream(bodyTmpFilePath));
+ bodyTmpFilePath.append("/").append(msg.getMsgId());
+ if (index > 0) {
+ bodyTmpFilePath.append("_" + index);
+ }
+ dos = new DataOutputStream(new FileOutputStream(bodyTmpFilePath.toString()));
dos.write(msg.getBody());
- return bodyTmpFilePath;
+ return bodyTmpFilePath.toString();
} finally {
if (dos != null)
dos.close();
@@ -195,6 +160,10 @@ public class QueryMsgByUniqueKeySubCommand implements SubCommand {
opt.setRequired(true);
options.addOption(opt);
+ opt = new Option("a", "showAll", false, "Print all message, the limit is 32");
+ opt.setRequired(false);
+ options.addOption(opt);
+
return options;
}
@@ -202,11 +171,11 @@ public class QueryMsgByUniqueKeySubCommand implements SubCommand {
public void execute(CommandLine commandLine, Options options, RPCHook rpcHook) throws SubCommandException {
try {
-
defaultMQAdminExt = createMQAdminExt(rpcHook);
final String msgId = commandLine.getOptionValue('i').trim();
final String topic = commandLine.getOptionValue('t').trim();
+ final boolean showAll = commandLine.hasOption('a');
if (commandLine.hasOption('g') && commandLine.hasOption('d')) {
final String consumerGroup = commandLine.getOptionValue('g').trim();
final String clientId = commandLine.getOptionValue('d').trim();
@@ -214,7 +183,7 @@ public class QueryMsgByUniqueKeySubCommand implements SubCommand {
defaultMQAdminExt.consumeMessageDirectly(consumerGroup, clientId, topic, msgId);
System.out.printf("%s", result);
} else {
- queryById(defaultMQAdminExt, topic, msgId);
+ queryById(defaultMQAdminExt, topic, msgId, showAll);
}
} catch (Exception e) {
throw new SubCommandException(this.getClass().getSimpleName() + " command failed", e);
diff --git a/tools/src/main/java/org/apache/rocketmq/tools/command/message/QueryMsgTraceByIdSubCommand.java b/tools/src/main/java/org/apache/rocketmq/tools/command/message/QueryMsgTraceByIdSubCommand.java
new file mode 100644
index 0000000000000000000000000000000000000000..7382ff568dcf04668687acf37eceacbbce1f614f
--- /dev/null
+++ b/tools/src/main/java/org/apache/rocketmq/tools/command/message/QueryMsgTraceByIdSubCommand.java
@@ -0,0 +1,154 @@
+/*
+ * 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.tools.command.message;
+
+import org.apache.commons.cli.CommandLine;
+import org.apache.commons.cli.Option;
+import org.apache.commons.cli.Options;
+import org.apache.commons.lang3.time.DateFormatUtils;
+import org.apache.rocketmq.client.QueryResult;
+import org.apache.rocketmq.client.exception.MQClientException;
+import org.apache.rocketmq.client.trace.TraceType;
+import org.apache.rocketmq.client.trace.TraceView;
+import org.apache.rocketmq.common.message.MessageExt;
+import org.apache.rocketmq.common.topic.TopicValidator;
+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.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+public class QueryMsgTraceByIdSubCommand implements SubCommand {
+
+ @Override
+ public Options buildCommandlineOptions(Options options) {
+ Option opt = new Option("i", "msgId", true, "Message Id");
+ opt.setRequired(true);
+ options.addOption(opt);
+
+ opt = new Option("t", "traceTopic", true, "The name value of message trace topic");
+ opt.setRequired(false);
+ options.addOption(opt);
+ return options;
+ }
+
+ @Override
+ public String commandDesc() {
+ return "query a message trace";
+ }
+
+ @Override
+ public String commandName() {
+ return "QueryMsgTraceById";
+ }
+
+ @Override
+ public void execute(CommandLine commandLine, Options options, RPCHook rpcHook) throws SubCommandException {
+ DefaultMQAdminExt defaultMQAdminExt = new DefaultMQAdminExt(rpcHook);
+ defaultMQAdminExt.setInstanceName(Long.toString(System.currentTimeMillis()));
+ try {
+ final String msgId = commandLine.getOptionValue('i').trim();
+ String traceTopic = TopicValidator.RMQ_SYS_TRACE_TOPIC;
+ if (commandLine.hasOption('t')) {
+ traceTopic = commandLine.getOptionValue('t').trim();
+ }
+ this.queryTraceByMsgId(defaultMQAdminExt, traceTopic, msgId);
+ } catch (Exception e) {
+ throw new SubCommandException(this.getClass().getSimpleName() + "command failed", e);
+ } finally {
+ defaultMQAdminExt.shutdown();
+ }
+ }
+
+ private void queryTraceByMsgId(final DefaultMQAdminExt admin, String traceTopic, String msgId)
+ throws MQClientException, InterruptedException {
+ admin.start();
+ QueryResult queryResult = admin.queryMessage(traceTopic, msgId, 64, 0, System.currentTimeMillis());
+ List messageList = queryResult.getMessageList();
+ List traceViews = new ArrayList<>();
+ for (MessageExt message : messageList) {
+ List traceView = TraceView.decodeFromTraceTransData(msgId, message);
+ traceViews.addAll(traceView);
+ }
+
+ this.printMessageTrace(traceViews);
+ }
+
+ private void printMessageTrace(List traceViews) {
+ Map> consumerTraceMap = new HashMap<>(16);
+ for (TraceView traceView : traceViews) {
+ if (traceView.getMsgType().equals(TraceType.Pub.name())) {
+ System.out.printf("%-10s %-20s %-20s %-20s %-10s %-10s%n",
+ "#Type",
+ "#ProducerGroup",
+ "#ClientHost",
+ "#SendTime",
+ "#CostTimes",
+ "#Status"
+ );
+ System.out.printf("%-10s %-20s %-20s %-20s %-10s %-10s%n",
+ "Pub",
+ traceView.getGroupName(),
+ traceView.getClientHost(),
+ DateFormatUtils.format(traceView.getTimeStamp(), "yyyy-MM-dd HH:mm:ss"),
+ traceView.getCostTime() + "ms",
+ traceView.getStatus()
+ );
+ System.out.printf("\n");
+ }
+ if (traceView.getMsgType().equals(TraceType.SubAfter.name())) {
+ String groupName = traceView.getGroupName();
+ if (consumerTraceMap.containsKey(groupName)) {
+ consumerTraceMap.get(groupName).add(traceView);
+ } else {
+ ArrayList views = new ArrayList<>();
+ views.add(traceView);
+ consumerTraceMap.put(groupName, views);
+ }
+ }
+ }
+
+ Iterator consumers = consumerTraceMap.keySet().iterator();
+ while (consumers.hasNext()) {
+ System.out.printf("%-10s %-20s %-20s %-20s %-10s %-10s%n",
+ "#Type",
+ "#ConsumerGroup",
+ "#ClientHost",
+ "#ConsumerTime",
+ "#CostTimes",
+ "#Status"
+ );
+ List consumerTraces = consumerTraceMap.get(consumers.next());
+ for (TraceView traceView : consumerTraces) {
+ System.out.printf("%-10s %-20s %-20s %-20s %-10s %-10s%n",
+ "Sub",
+ traceView.getGroupName(),
+ traceView.getClientHost(),
+ DateFormatUtils.format(traceView.getTimeStamp(), "yyyy-MM-dd HH:mm:ss"),
+ traceView.getCostTime() + "ms",
+ traceView.getStatus()
+ );
+ }
+ System.out.printf("\n");
+ }
+ }
+}
\ No newline at end of file
diff --git a/tools/src/main/java/org/apache/rocketmq/tools/command/message/SendMessageCommand.java b/tools/src/main/java/org/apache/rocketmq/tools/command/message/SendMessageCommand.java
index e4921c6f04ef0839bf60bf68835e17234b2cafae..9550742e8f7fa25c154a844ab49a63de3fe9a82f 100644
--- a/tools/src/main/java/org/apache/rocketmq/tools/command/message/SendMessageCommand.java
+++ b/tools/src/main/java/org/apache/rocketmq/tools/command/message/SendMessageCommand.java
@@ -68,14 +68,18 @@ public class SendMessageCommand implements SubCommand {
opt.setRequired(false);
options.addOption(opt);
+ opt = new Option("m", "msgTraceEnable", true, "Message Trace Enable, Default: false");
+ opt.setRequired(false);
+ options.addOption(opt);
+
return options;
}
- private DefaultMQProducer createProducer(RPCHook rpcHook) {
+ private DefaultMQProducer createProducer(RPCHook rpcHook, boolean msgTraceEnable) {
if (this.producer != null) {
return producer;
} else {
- producer = new DefaultMQProducer(rpcHook);
+ producer = new DefaultMQProducer(null, rpcHook, msgTraceEnable, null);
producer.setProducerGroup(Long.toString(System.currentTimeMillis()));
return producer;
}
@@ -112,8 +116,11 @@ public class SendMessageCommand implements SubCommand {
} catch (Exception e) {
throw new RuntimeException(this.getClass().getSimpleName() + " command failed", e);
}
-
- DefaultMQProducer producer = this.createProducer(rpcHook);
+ boolean msgTraceEnable = false;
+ if (commandLine.hasOption('m')) {
+ msgTraceEnable = Boolean.parseBoolean(commandLine.getOptionValue('m').trim());
+ }
+ DefaultMQProducer producer = this.createProducer(rpcHook, msgTraceEnable);
SendResult result;
try {
producer.start();
@@ -153,4 +160,4 @@ public class SendMessageCommand implements SubCommand {
);
}
}
-}
\ No newline at end of file
+}
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 c770db01d427c9e33c17a8a6cc20a76ed6760dfc..a78a4a63ab0eb6495561eaf734f06cffd8a627c7 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 a06a19d1fd08e800d51ffe58bae006b3140ee8df..63a2a19275a65b9078beb23324c61a5260f6b41d 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')) {
diff --git a/tools/src/main/java/org/apache/rocketmq/tools/monitor/MonitorService.java b/tools/src/main/java/org/apache/rocketmq/tools/monitor/MonitorService.java
index 9bf09ad410754be36bb2cb75e01761d83a02288c..94f588da27537575e8e99fc73b5e707425edc417 100644
--- a/tools/src/main/java/org/apache/rocketmq/tools/monitor/MonitorService.java
+++ b/tools/src/main/java/org/apache/rocketmq/tools/monitor/MonitorService.java
@@ -40,6 +40,7 @@ import org.apache.rocketmq.common.MixAll;
import org.apache.rocketmq.common.ThreadFactoryImpl;
import org.apache.rocketmq.common.admin.ConsumeStats;
import org.apache.rocketmq.common.admin.OffsetWrapper;
+import org.apache.rocketmq.common.topic.TopicValidator;
import org.apache.rocketmq.logging.InternalLogger;
import org.apache.rocketmq.common.message.MessageExt;
import org.apache.rocketmq.common.message.MessageQueue;
@@ -83,7 +84,7 @@ public class MonitorService {
try {
this.defaultMQPushConsumer.setConsumeThreadMin(1);
this.defaultMQPushConsumer.setConsumeThreadMax(1);
- this.defaultMQPushConsumer.subscribe(MixAll.OFFSET_MOVED_EVENT, "*");
+ this.defaultMQPushConsumer.subscribe(TopicValidator.RMQ_SYS_OFFSET_MOVED_EVENT, "*");
this.defaultMQPushConsumer.registerMessageListener(new MessageListenerConcurrently() {
@Override
diff --git a/tools/src/test/java/org/apache/rocketmq/tools/command/message/QueryMsgTraceByIdSubCommandTest.java b/tools/src/test/java/org/apache/rocketmq/tools/command/message/QueryMsgTraceByIdSubCommandTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..f61c71d109297e31170f3ce414ce55fa72bd6f98
--- /dev/null
+++ b/tools/src/test/java/org/apache/rocketmq/tools/command/message/QueryMsgTraceByIdSubCommandTest.java
@@ -0,0 +1,84 @@
+/*
+ * 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.tools.command.message;
+
+import org.apache.commons.cli.CommandLine;
+import org.apache.commons.cli.Options;
+import org.apache.commons.cli.PosixParser;
+import org.apache.rocketmq.client.ClientConfig;
+import org.apache.rocketmq.client.exception.MQBrokerException;
+import org.apache.rocketmq.client.exception.MQClientException;
+import org.apache.rocketmq.client.impl.MQClientAPIImpl;
+import org.apache.rocketmq.client.impl.MQClientManager;
+import org.apache.rocketmq.client.impl.factory.MQClientInstance;
+import org.apache.rocketmq.remoting.exception.RemotingConnectException;
+import org.apache.rocketmq.remoting.exception.RemotingSendRequestException;
+import org.apache.rocketmq.remoting.exception.RemotingTimeoutException;
+import org.apache.rocketmq.srvutil.ServerUtil;
+import org.apache.rocketmq.tools.admin.DefaultMQAdminExt;
+import org.apache.rocketmq.tools.admin.DefaultMQAdminExtImpl;
+import org.apache.rocketmq.tools.command.SubCommandException;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Ignore;
+import org.junit.Test;
+
+import java.io.UnsupportedEncodingException;
+import java.lang.reflect.Field;
+
+import static org.mockito.Mockito.mock;
+
+public class QueryMsgTraceByIdSubCommandTest {
+ private static DefaultMQAdminExt defaultMQAdminExt;
+ private static DefaultMQAdminExtImpl defaultMQAdminExtImpl;
+ private static MQClientInstance mqClientInstance = MQClientManager.getInstance().getOrCreateMQClientInstance(new ClientConfig());
+ private static MQClientAPIImpl mQClientAPIImpl;
+
+ @BeforeClass
+ public static void init() throws NoSuchFieldException, IllegalAccessException, InterruptedException, RemotingTimeoutException, MQClientException, RemotingSendRequestException, RemotingConnectException, MQBrokerException, UnsupportedEncodingException {
+ mQClientAPIImpl = mock(MQClientAPIImpl.class);
+ defaultMQAdminExt = new DefaultMQAdminExt();
+ defaultMQAdminExtImpl = new DefaultMQAdminExtImpl(defaultMQAdminExt, 1000);
+
+ Field field = DefaultMQAdminExtImpl.class.getDeclaredField("mqClientInstance");
+ field.setAccessible(true);
+ field.set(defaultMQAdminExtImpl, mqClientInstance);
+ field = MQClientInstance.class.getDeclaredField("mQClientAPIImpl");
+ field.setAccessible(true);
+ field.set(mqClientInstance, mQClientAPIImpl);
+ field = DefaultMQAdminExt.class.getDeclaredField("defaultMQAdminExtImpl");
+ field.setAccessible(true);
+ field.set(defaultMQAdminExt, defaultMQAdminExtImpl);
+ }
+
+ @AfterClass
+ public static void terminate() {
+ defaultMQAdminExt.shutdown();
+ }
+
+ @Ignore
+ @Test
+ public void testExecute() throws SubCommandException {
+ System.setProperty("rocketmq.namesrv.addr", "127.0.0.1:9876");
+ QueryMsgTraceByIdSubCommand cmd = new QueryMsgTraceByIdSubCommand();
+ Options options = ServerUtil.buildCommandlineOptions(new Options());
+ String[] subargs = new String[] {"-i AC1FF54E81C418B4AAC24F92E1E00000"};
+ final CommandLine commandLine =
+ ServerUtil.parseCmdLine("mqadmin " + cmd.commandName(), subargs, cmd.buildCommandlineOptions(options), new PosixParser());
+ cmd.execute(commandLine, options, null);
+ }
+}
\ No newline at end of file