提交 c6cbab99 编写于 作者: Q qqeasonchen

resolve Conflicts:

#	broker/src/main/java/org/apache/rocketmq/broker/BrokerController.java
...@@ -8,10 +8,12 @@ ...@@ -8,10 +8,12 @@
It offers a variety of features: It offers a variety of features:
* Pub/Sub messaging model * Pub/Sub messaging model
* Scheduled message delivery * Financial grade transactional message
* A variety of cross language clients, such as Java, C/C++, Python, Go
* Pluggable transport protocols, such as TCP, SSL, AIO
* Inbuilt message tracing capability, also support opentracing
* Versatile big-data and streaming ecosytem integration
* Message retroactivity by time or offset * Message retroactivity by time or offset
* Log hub for streaming
* Big data integration
* Reliable FIFO and strict ordered messaging in the same queue * Reliable FIFO and strict ordered messaging in the same queue
* Efficient pull&push consumption model * Efficient pull&push consumption model
* Million-level message accumulation capacity in a single queue * Million-level message accumulation capacity in a single queue
...@@ -21,9 +23,7 @@ It offers a variety of features: ...@@ -21,9 +23,7 @@ It offers a variety of features:
* Various message filter mechanics such as SQL and Tag * Various message filter mechanics such as SQL and Tag
* Docker images for isolated testing and cloud isolated clusters * Docker images for isolated testing and cloud isolated clusters
* Feature-rich administrative dashboard for configuration, metrics and monitoring * Feature-rich administrative dashboard for configuration, metrics and monitoring
* Access control list * Authentication and authorisation
* Message trace
---------- ----------
......
...@@ -67,6 +67,10 @@ ...@@ -67,6 +67,10 @@
<artifactId>logback-core</artifactId> <artifactId>logback-core</artifactId>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency>
<groupId>commons-validator</groupId>
<artifactId>commons-validator</artifactId>
</dependency>
</dependencies> </dependencies>
</project> </project>
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
package org.apache.rocketmq.acl; package org.apache.rocketmq.acl;
import java.util.List; import java.util.List;
import org.apache.rocketmq.common.AclConfig;
import org.apache.rocketmq.common.PlainAccessConfig; import org.apache.rocketmq.common.PlainAccessConfig;
import org.apache.rocketmq.remoting.protocol.RemotingCommand; import org.apache.rocketmq.remoting.protocol.RemotingCommand;
...@@ -66,4 +67,10 @@ public interface AccessValidator { ...@@ -66,4 +67,10 @@ public interface AccessValidator {
* @return * @return
*/ */
boolean updateGlobalWhiteAddrsConfig(List<String> globalWhiteAddrsList); boolean updateGlobalWhiteAddrsConfig(List<String> globalWhiteAddrsList);
/**
* get broker cluster acl config information
* @return
*/
AclConfig getAllAclConfig();
} }
...@@ -23,6 +23,7 @@ import java.io.FileNotFoundException; ...@@ -23,6 +23,7 @@ import java.io.FileNotFoundException;
import java.io.FileWriter; import java.io.FileWriter;
import java.io.IOException; import java.io.IOException;
import java.io.PrintWriter; import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Map; import java.util.Map;
import java.util.SortedMap; import java.util.SortedMap;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
...@@ -69,24 +70,75 @@ public class AclUtils { ...@@ -69,24 +70,75 @@ public class AclUtils {
return signature; return signature;
} }
public static void IPv6AddressCheck(String netaddress) {
if (isAsterisk(netaddress) || isMinus(netaddress)) {
int asterisk = netaddress.indexOf("*");
int minus = netaddress.indexOf("-");
// '*' must be the end of netaddress if it exists
if (asterisk > -1 && asterisk != netaddress.length() - 1) {
throw new AclException(String.format("Netaddress examine scope Exception netaddress is %s", netaddress));
}
// format like "2::ac5:78:1-200:*" or "2::ac5:78:1-200" is legal
if (minus > -1) {
if (asterisk == -1) {
if (minus <= netaddress.lastIndexOf(":")) {
throw new AclException(String.format("Netaddress examine scope Exception netaddress is %s", netaddress));
}
} else {
if (minus <= netaddress.lastIndexOf(":", netaddress.lastIndexOf(":") - 1)) {
throw new AclException(String.format("Netaddress examine scope Exception netaddress is %s", netaddress));
}
}
}
}
}
public static String v6ipProcess(String netaddress, String[] strArray, int index) {
int part;
String subAddress;
boolean isAsterisk = isAsterisk(netaddress);
boolean isMinus = isMinus(netaddress);
if (isAsterisk && isMinus) {
part = 6;
int lastColon = netaddress.lastIndexOf(':');
int secondLastColon = netaddress.substring(0, lastColon).lastIndexOf(':');
subAddress = netaddress.substring(0, secondLastColon);
} else if (!isAsterisk && !isMinus) {
part = 8;
subAddress = netaddress;
} else {
part = 7;
subAddress = netaddress.substring(0, netaddress.lastIndexOf(':'));
}
return expandIP(subAddress, part);
}
public static void verify(String netaddress, int index) { public static void verify(String netaddress, int index) {
if (!AclUtils.isScope(netaddress, index)) { if (!AclUtils.isScope(netaddress, index)) {
throw new AclException(String.format("Netaddress examine scope Exception netaddress is %s", netaddress)); throw new AclException(String.format("Netaddress examine scope Exception netaddress is %s", netaddress));
} }
} }
public static String[] getAddreeStrArray(String netaddress, String four) { public static String[] getAddreeStrArray(String netaddress, String partialAddress) {
String[] fourStrArray = StringUtils.split(four.substring(1, four.length() - 1), ","); String[] parAddStrArray = StringUtils.split(partialAddress.substring(1, partialAddress.length() - 1), ",");
String address = netaddress.substring(0, netaddress.indexOf("{")); String address = netaddress.substring(0, netaddress.indexOf("{"));
String[] addreeStrArray = new String[fourStrArray.length]; String[] addreeStrArray = new String[parAddStrArray.length];
for (int i = 0; i < fourStrArray.length; i++) { for (int i = 0; i < parAddStrArray.length; i++) {
addreeStrArray[i] = address + fourStrArray[i]; addreeStrArray[i] = address + parAddStrArray[i];
} }
return addreeStrArray; return addreeStrArray;
} }
public static boolean isScope(String num, int index) { public static boolean isScope(String netaddress, int index) {
String[] strArray = StringUtils.split(num, "."); // IPv6 Address
if (isColon(netaddress)) {
netaddress = expandIP(netaddress, 8);
String[] strArray = StringUtils.split(netaddress, ":");
return isIPv6Scope(strArray, index);
}
String[] strArray = StringUtils.split(netaddress, ".");
if (strArray.length != 4) { if (strArray.length != 4) {
return false; return false;
} }
...@@ -107,6 +159,10 @@ public class AclUtils { ...@@ -107,6 +159,10 @@ public class AclUtils {
} }
public static boolean isColon(String netaddress) {
return netaddress.indexOf(':') > -1;
}
public static boolean isScope(String num) { public static boolean isScope(String num) {
return isScope(Integer.valueOf(num.trim())); return isScope(Integer.valueOf(num.trim()));
} }
...@@ -119,7 +175,7 @@ public class AclUtils { ...@@ -119,7 +175,7 @@ public class AclUtils {
return asterisk.indexOf('*') > -1; return asterisk.indexOf('*') > -1;
} }
public static boolean isColon(String colon) { public static boolean isComma(String colon) {
return colon.indexOf(',') > -1; return colon.indexOf(',') > -1;
} }
...@@ -128,6 +184,88 @@ public class AclUtils { ...@@ -128,6 +184,88 @@ public class AclUtils {
} }
public static boolean isIPv6Scope(String[] num, int index) {
for (int i = 0; i < index; i++) {
int value;
try {
value = Integer.parseInt(num[i], 16);
} catch (NumberFormatException e) {
return false;
}
if (!isIPv6Scope(value)) {
return false;
}
}
return true;
}
public static boolean isIPv6Scope(int num) {
int min = Integer.parseInt("0", 16);
int max = Integer.parseInt("ffff", 16);
return num >= min && num <= max;
}
public static String expandIP(String netaddress, int part) {
boolean compress = false;
int compressIndex = -1;
String[] strArray = StringUtils.split(netaddress, ":");
ArrayList<Integer> indexes = new ArrayList<>();
for (int i = 0; i < netaddress.length(); i++) {
if (netaddress.charAt(i) == ':') {
if (indexes.size() > 0 && i - indexes.get(indexes.size() - 1) == 1) {
compressIndex = i;
compress = true;
}
indexes.add(i);
}
}
for (int i = 0; i < strArray.length; i++) {
if (strArray[i].length() < 4) {
strArray[i] = "0000".substring(0, 4 - strArray[i].length()) + strArray[i];
}
}
StringBuilder sb = new StringBuilder();
if (compress) {
int pos = indexes.indexOf(compressIndex);
int index = 0;
if (!netaddress.startsWith(":")) {
for (int i = 0; i < pos; i++) {
sb.append(strArray[index]).append(":");
index += 1;
}
}
int zeroNum = part - strArray.length;
if (netaddress.endsWith(":")) {
for (int i = 0; i < zeroNum; i++) {
sb.append("0000");
if (i != zeroNum - 1) {
sb.append(":");
}
}
} else {
for (int i = 0; i < zeroNum; i++) {
sb.append("0000").append(":");
}
for (int i = index; i < strArray.length; i++) {
sb.append(strArray[i]);
if (i != strArray.length - 1) {
sb.append(":");
}
}
}
} else {
for (int i = 0; i < strArray.length; i++) {
sb.append(strArray[i]);
if (i != strArray.length - 1) {
sb.append(":");
}
}
}
return sb.toString().toUpperCase();
}
public static <T> T getYamlDataObject(String path, Class<T> clazz) { public static <T> T getYamlDataObject(String path, Class<T> clazz) {
Yaml yaml = new Yaml(); Yaml yaml = new Yaml();
FileInputStream fis = null; FileInputStream fis = null;
...@@ -148,7 +286,7 @@ public class AclUtils { ...@@ -148,7 +286,7 @@ public class AclUtils {
} }
} }
public static boolean writeDataObject(String path, Map<String,Object> dataMap) { public static boolean writeDataObject(String path, Map<String, Object> dataMap) {
Yaml yaml = new Yaml(); Yaml yaml = new Yaml();
PrintWriter pw = null; PrintWriter pw = null;
try { try {
...@@ -172,15 +310,15 @@ public class AclUtils { ...@@ -172,15 +310,15 @@ public class AclUtils {
yamlDataObject = AclUtils.getYamlDataObject(fileName, yamlDataObject = AclUtils.getYamlDataObject(fileName,
JSONObject.class); JSONObject.class);
} catch (Exception e) { } catch (Exception e) {
log.error("Convert yaml file to data object error, ",e); log.error("Convert yaml file to data object error, ", e);
return null; return null;
} }
if (yamlDataObject == null || yamlDataObject.isEmpty()) { if (yamlDataObject == null || yamlDataObject.isEmpty()) {
log.warn("Cannot find conf file :{}, acl isn't be enabled." ,fileName); log.warn("Cannot find conf file :{}, acl isn't be enabled.", fileName);
return null; return null;
} }
String accessKey = yamlDataObject.getString(AclConstants.CONFIG_ACCESS_KEY); String accessKey = yamlDataObject.getString(AclConstants.CONFIG_ACCESS_KEY);
String secretKey = yamlDataObject.getString(AclConstants.CONFIG_SECRET_KEY); String secretKey = yamlDataObject.getString(AclConstants.CONFIG_SECRET_KEY);
...@@ -189,7 +327,7 @@ public class AclUtils { ...@@ -189,7 +327,7 @@ public class AclUtils {
return null; return null;
} }
return new AclClientRPCHook(new SessionCredentials(accessKey,secretKey)); return new AclClientRPCHook(new SessionCredentials(accessKey, secretKey));
} }
} }
...@@ -26,6 +26,7 @@ import org.apache.rocketmq.acl.common.AclException; ...@@ -26,6 +26,7 @@ import org.apache.rocketmq.acl.common.AclException;
import org.apache.rocketmq.acl.common.AclUtils; import org.apache.rocketmq.acl.common.AclUtils;
import org.apache.rocketmq.acl.common.Permission; import org.apache.rocketmq.acl.common.Permission;
import org.apache.rocketmq.acl.common.SessionCredentials; import org.apache.rocketmq.acl.common.SessionCredentials;
import org.apache.rocketmq.common.AclConfig;
import org.apache.rocketmq.common.PlainAccessConfig; import org.apache.rocketmq.common.PlainAccessConfig;
import org.apache.rocketmq.common.protocol.RequestCode; import org.apache.rocketmq.common.protocol.RequestCode;
import org.apache.rocketmq.common.protocol.header.GetConsumerListByGroupRequestHeader; import org.apache.rocketmq.common.protocol.header.GetConsumerListByGroupRequestHeader;
...@@ -50,7 +51,7 @@ public class PlainAccessValidator implements AccessValidator { ...@@ -50,7 +51,7 @@ public class PlainAccessValidator implements AccessValidator {
public AccessResource parse(RemotingCommand request, String remoteAddr) { public AccessResource parse(RemotingCommand request, String remoteAddr) {
PlainAccessResource accessResource = new PlainAccessResource(); PlainAccessResource accessResource = new PlainAccessResource();
if (remoteAddr != null && remoteAddr.contains(":")) { if (remoteAddr != null && remoteAddr.contains(":")) {
accessResource.setWhiteRemoteAddress(remoteAddr.split(":")[0]); accessResource.setWhiteRemoteAddress(remoteAddr.substring(0, remoteAddr.lastIndexOf(':')));
} else { } else {
accessResource.setWhiteRemoteAddress(remoteAddr); accessResource.setWhiteRemoteAddress(remoteAddr);
} }
...@@ -155,4 +156,7 @@ public class PlainAccessValidator implements AccessValidator { ...@@ -155,4 +156,7 @@ public class PlainAccessValidator implements AccessValidator {
return aclPlugEngine.updateGlobalWhiteAddrsConfig(globalWhiteAddrsList); return aclPlugEngine.updateGlobalWhiteAddrsConfig(globalWhiteAddrsList);
} }
@Override public AclConfig getAllAclConfig() {
return aclPlugEngine.getAllAclConfig();
}
} }
...@@ -30,6 +30,7 @@ import org.apache.rocketmq.acl.common.AclConstants; ...@@ -30,6 +30,7 @@ import org.apache.rocketmq.acl.common.AclConstants;
import org.apache.rocketmq.acl.common.AclException; import org.apache.rocketmq.acl.common.AclException;
import org.apache.rocketmq.acl.common.AclUtils; import org.apache.rocketmq.acl.common.AclUtils;
import org.apache.rocketmq.acl.common.Permission; import org.apache.rocketmq.acl.common.Permission;
import org.apache.rocketmq.common.AclConfig;
import org.apache.rocketmq.common.DataVersion; import org.apache.rocketmq.common.DataVersion;
import org.apache.rocketmq.common.MixAll; import org.apache.rocketmq.common.MixAll;
import org.apache.rocketmq.common.PlainAccessConfig; import org.apache.rocketmq.common.PlainAccessConfig;
...@@ -270,6 +271,28 @@ public class PlainPermissionManager { ...@@ -270,6 +271,28 @@ public class PlainPermissionManager {
return false; return false;
} }
public AclConfig getAllAclConfig() {
AclConfig aclConfig = new AclConfig();
List<PlainAccessConfig> configs = new ArrayList<>();
List<String> whiteAddrs = new ArrayList<>();
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));
}
JSONArray globalWhiteAddrs = plainAclConfData.getJSONArray(AclConstants.CONFIG_GLOBAL_WHITE_ADDRS);
if (globalWhiteAddrs != null && !globalWhiteAddrs.isEmpty()) {
whiteAddrs = globalWhiteAddrs.toJavaList(String.class);
}
JSONArray accounts = plainAclConfData.getJSONArray(AclConstants.CONFIG_ACCOUNTS);
if (accounts != null && !accounts.isEmpty()) {
configs = accounts.toJavaList(PlainAccessConfig.class);
}
aclConfig.setGlobalWhiteAddrs(whiteAddrs);
aclConfig.setPlainAccessConfigs(configs);
return aclConfig;
}
private void watch() { private void watch() {
try { try {
String watchFilePath = fileHome + fileName; String watchFilePath = fileHome + fileName;
......
...@@ -19,6 +19,7 @@ package org.apache.rocketmq.acl.plain; ...@@ -19,6 +19,7 @@ package org.apache.rocketmq.acl.plain;
import java.util.HashSet; import java.util.HashSet;
import java.util.Set; import java.util.Set;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.apache.commons.validator.routines.InetAddressValidator;
import org.apache.rocketmq.acl.common.AclException; import org.apache.rocketmq.acl.common.AclException;
import org.apache.rocketmq.acl.common.AclUtils; import org.apache.rocketmq.acl.common.AclUtils;
import org.apache.rocketmq.common.constant.LoggerName; import org.apache.rocketmq.common.constant.LoggerName;
...@@ -41,17 +42,26 @@ public class RemoteAddressStrategyFactory { ...@@ -41,17 +42,26 @@ public class RemoteAddressStrategyFactory {
if (StringUtils.isBlank(remoteAddr)) { if (StringUtils.isBlank(remoteAddr)) {
return BLANK_NET_ADDRESS_STRATEGY; return BLANK_NET_ADDRESS_STRATEGY;
} }
if ("*".equals(remoteAddr) || "*.*.*.*".equals(remoteAddr)) { if ("*".equals(remoteAddr) || "*.*.*.*".equals(remoteAddr) || "*:*:*:*:*:*:*:*".equals(remoteAddr)) {
return NULL_NET_ADDRESS_STRATEGY; return NULL_NET_ADDRESS_STRATEGY;
} }
if (remoteAddr.endsWith("}")) { if (remoteAddr.endsWith("}")) {
String[] strArray = StringUtils.split(remoteAddr, "."); if (AclUtils.isColon(remoteAddr)) {
String four = strArray[3]; String[] strArray = StringUtils.split(remoteAddr, ":");
if (!four.startsWith("{")) { String last = strArray[strArray.length - 1];
throw new AclException(String.format("MultipleRemoteAddressStrategy netaddress examine scope Exception netaddress", remoteAddr)); if (!last.startsWith("{")) {
throw new AclException(String.format("MultipleRemoteAddressStrategy netaddress examine scope Exception netaddress", remoteAddr));
}
return new MultipleRemoteAddressStrategy(AclUtils.getAddreeStrArray(remoteAddr, last));
} else {
String[] strArray = StringUtils.split(remoteAddr, ".");
String four = strArray[3];
if (!four.startsWith("{")) {
throw new AclException(String.format("MultipleRemoteAddressStrategy netaddress examine scope Exception netaddress", remoteAddr));
}
return new MultipleRemoteAddressStrategy(AclUtils.getAddreeStrArray(remoteAddr, four));
} }
return new MultipleRemoteAddressStrategy(AclUtils.getAddreeStrArray(remoteAddr, four)); } else if (AclUtils.isComma(remoteAddr)) {
} else if (AclUtils.isColon(remoteAddr)) {
return new MultipleRemoteAddressStrategy(StringUtils.split(remoteAddr, ",")); return new MultipleRemoteAddressStrategy(StringUtils.split(remoteAddr, ","));
} else if (AclUtils.isAsterisk(remoteAddr) || AclUtils.isMinus(remoteAddr)) { } else if (AclUtils.isAsterisk(remoteAddr) || AclUtils.isMinus(remoteAddr)) {
return new RangeRemoteAddressStrategy(remoteAddr); return new RangeRemoteAddressStrategy(remoteAddr);
...@@ -81,15 +91,26 @@ public class RemoteAddressStrategyFactory { ...@@ -81,15 +91,26 @@ public class RemoteAddressStrategyFactory {
private final Set<String> multipleSet = new HashSet<>(); private final Set<String> multipleSet = new HashSet<>();
public MultipleRemoteAddressStrategy(String[] strArray) { public MultipleRemoteAddressStrategy(String[] strArray) {
InetAddressValidator validator = InetAddressValidator.getInstance();
for (String netaddress : strArray) { for (String netaddress : strArray) {
AclUtils.verify(netaddress, 4); if (validator.isValidInet4Address(netaddress)) {
multipleSet.add(netaddress); multipleSet.add(netaddress);
} else if (validator.isValidInet6Address(netaddress)) {
multipleSet.add(AclUtils.expandIP(netaddress, 8));
} else {
throw new AclException(String.format("Netaddress examine Exception netaddress is %s", netaddress));
}
} }
} }
@Override @Override
public boolean match(PlainAccessResource plainAccessResource) { public boolean match(PlainAccessResource plainAccessResource) {
return multipleSet.contains(plainAccessResource.getWhiteRemoteAddress()); InetAddressValidator validator = InetAddressValidator.getInstance();
String whiteRemoteAddress = plainAccessResource.getWhiteRemoteAddress();
if (validator.isValidInet6Address(whiteRemoteAddress)) {
whiteRemoteAddress = AclUtils.expandIP(whiteRemoteAddress, 8);
}
return multipleSet.contains(whiteRemoteAddress);
} }
} }
...@@ -100,12 +121,16 @@ public class RemoteAddressStrategyFactory { ...@@ -100,12 +121,16 @@ public class RemoteAddressStrategyFactory {
public OneRemoteAddressStrategy(String netaddress) { public OneRemoteAddressStrategy(String netaddress) {
this.netaddress = netaddress; this.netaddress = netaddress;
AclUtils.verify(netaddress, 4); InetAddressValidator validator = InetAddressValidator.getInstance();
if (!(validator.isValidInet4Address(netaddress) || validator.isValidInet6Address(netaddress))) {
throw new AclException(String.format("Netaddress examine Exception netaddress is %s", netaddress));
}
} }
@Override @Override
public boolean match(PlainAccessResource plainAccessResource) { public boolean match(PlainAccessResource plainAccessResource) {
return netaddress.equals(plainAccessResource.getWhiteRemoteAddress()); String writeRemoteAddress = AclUtils.expandIP(plainAccessResource.getWhiteRemoteAddress(), 8).toUpperCase();
return AclUtils.expandIP(netaddress, 8).toUpperCase().equals(writeRemoteAddress);
} }
} }
...@@ -121,14 +146,29 @@ public class RemoteAddressStrategyFactory { ...@@ -121,14 +146,29 @@ public class RemoteAddressStrategyFactory {
private int index; private int index;
public RangeRemoteAddressStrategy(String remoteAddr) { public RangeRemoteAddressStrategy(String remoteAddr) {
String[] strArray = StringUtils.split(remoteAddr, "."); // IPv6 Address
if (analysis(strArray, 1) || analysis(strArray, 2) || analysis(strArray, 3)) { if (AclUtils.isColon(remoteAddr)) {
AclUtils.verify(remoteAddr, index - 1); AclUtils.IPv6AddressCheck(remoteAddr);
StringBuffer sb = new StringBuffer().append(strArray[0].trim()).append(".").append(strArray[1].trim()).append("."); String[] strArray = StringUtils.split(remoteAddr, ":");
if (index == 3) { for (int i = 1; i < strArray.length; i++) {
sb.append(strArray[2].trim()).append("."); if (ipv6Analysis(strArray, i)) {
AclUtils.verify(remoteAddr, index - 1);
String preAddress = AclUtils.v6ipProcess(remoteAddr, strArray, index);
this.index = StringUtils.split(preAddress, ":").length;
this.head = preAddress;
break;
}
}
} else {
String[] strArray = StringUtils.split(remoteAddr, ".");
if (analysis(strArray, 1) || analysis(strArray, 2) || analysis(strArray, 3)) {
AclUtils.verify(remoteAddr, index - 1);
StringBuffer sb = new StringBuffer();
for (int j = 0; j < index; j++) {
sb.append(strArray[j].trim()).append(".");
}
this.head = sb.toString();
} }
this.head = sb.toString();
} }
} }
...@@ -152,6 +192,27 @@ public class RemoteAddressStrategyFactory { ...@@ -152,6 +192,27 @@ public class RemoteAddressStrategyFactory {
return this.end > 0 ? true : false; return this.end > 0 ? true : false;
} }
private boolean ipv6Analysis(String[] strArray, int index) {
String value = strArray[index].trim();
this.index = index;
if ("*".equals(value)) {
int min = Integer.parseInt("0", 16);
int max = Integer.parseInt("ffff", 16);
setValue(min, max);
} else if (AclUtils.isMinus(value)) {
if (value.indexOf("-") == 0) {
throw new AclException(String.format("RangeRemoteAddressStrategy netaddress examine scope Exception value %s ", value));
}
String[] valueArray = StringUtils.split(value, "-");
this.start = Integer.parseInt(valueArray[0], 16);
this.end = Integer.parseInt(valueArray[1], 16);
if (!(AclUtils.isIPv6Scope(end) && AclUtils.isIPv6Scope(start) && start <= end)) {
throw new AclException(String.format("RangeRemoteAddressStrategy netaddress examine scope Exception start is %s , end is %s", start, end));
}
}
return this.end > 0 ? true : false;
}
private void setValue(int start, int end) { private void setValue(int start, int end) {
this.start = start; this.start = start;
this.end = end; this.end = end;
...@@ -160,21 +221,33 @@ public class RemoteAddressStrategyFactory { ...@@ -160,21 +221,33 @@ public class RemoteAddressStrategyFactory {
@Override @Override
public boolean match(PlainAccessResource plainAccessResource) { public boolean match(PlainAccessResource plainAccessResource) {
String netAddress = plainAccessResource.getWhiteRemoteAddress(); String netAddress = plainAccessResource.getWhiteRemoteAddress();
if (netAddress.startsWith(this.head)) { InetAddressValidator validator = InetAddressValidator.getInstance();
String value; if (validator.isValidInet4Address(netAddress)) {
if (index == 3) { if (netAddress.startsWith(this.head)) {
value = netAddress.substring(this.head.length()); String value;
} else { if (index == 3) {
value = netAddress.substring(this.head.length(), netAddress.lastIndexOf('.')); value = netAddress.substring(this.head.length());
} else if (index == 2) {
value = netAddress.substring(this.head.length(), netAddress.lastIndexOf('.'));
} else {
value = netAddress.substring(this.head.length(), netAddress.lastIndexOf('.', netAddress.lastIndexOf('.') - 1));
}
Integer address = Integer.valueOf(value);
if (address >= this.start && address <= this.end) {
return true;
}
} }
Integer address = Integer.valueOf(value); } else if (validator.isValidInet6Address(netAddress)) {
if (address >= this.start && address <= this.end) { netAddress = AclUtils.expandIP(netAddress, 8).toUpperCase();
return true; if (netAddress.startsWith(this.head)) {
String value = netAddress.substring(5 * index, 5 * index + 4);
Integer address = Integer.parseInt(value, 16);
if (address >= this.start && address <= this.end) {
return true;
}
} }
} }
return false; return false;
} }
} }
} }
...@@ -46,20 +46,35 @@ public class AclUtilsTest { ...@@ -46,20 +46,35 @@ public class AclUtilsTest {
addressList.add("1.1.1.3"); addressList.add("1.1.1.3");
addressList.add("1.1.1.4"); addressList.add("1.1.1.4");
Assert.assertEquals(newAddressList, addressList); Assert.assertEquals(newAddressList, addressList);
// IPv6 test
String ipv6Address = "1:ac41:9987::bb22:666:{1,2,3,4}";
String[] ipv6AddressArray = AclUtils.getAddreeStrArray(ipv6Address, "{1,2,3,4}");
List<String> newIPv6AddressList = new ArrayList<>();
for (String a : ipv6AddressArray) {
newIPv6AddressList.add(a);
}
List<String> ipv6AddressList = new ArrayList<>();
ipv6AddressList.add("1:ac41:9987::bb22:666:1");
ipv6AddressList.add("1:ac41:9987::bb22:666:2");
ipv6AddressList.add("1:ac41:9987::bb22:666:3");
ipv6AddressList.add("1:ac41:9987::bb22:666:4");
Assert.assertEquals(newIPv6AddressList, ipv6AddressList);
} }
@Test @Test
public void isScopeStringArray() { public void isScopeStringArray() {
String adderss = "12"; String address = "12";
for (int i = 0; i < 6; i++) { for (int i = 0; i < 6; i++) {
boolean isScope = AclUtils.isScope(adderss, 4); boolean isScope = AclUtils.isScope(address, 4);
if (i == 3) { if (i == 3) {
Assert.assertTrue(isScope); Assert.assertTrue(isScope);
} else { } else {
Assert.assertFalse(isScope); Assert.assertFalse(isScope);
} }
adderss = adderss + ".12"; address = address + ".12";
} }
} }
...@@ -77,6 +92,25 @@ public class AclUtilsTest { ...@@ -77,6 +92,25 @@ public class AclUtilsTest {
isScope = AclUtils.isScope(adderss, 3); isScope = AclUtils.isScope(adderss, 3);
Assert.assertFalse(isScope); Assert.assertFalse(isScope);
// IPv6 test
adderss = StringUtils.split("1050:0000:0000:0000:0005:0600:300c:326b", ":");
isScope = AclUtils.isIPv6Scope(adderss, 8);
Assert.assertTrue(isScope);
isScope = AclUtils.isIPv6Scope(adderss, 4);
Assert.assertTrue(isScope);
adderss = StringUtils.split("1050:9876:0000:0000:0005:akkg:300c:326b", ":");
isScope = AclUtils.isIPv6Scope(adderss, 8);
Assert.assertFalse(isScope);
isScope = AclUtils.isIPv6Scope(adderss, 4);
Assert.assertTrue(isScope);
adderss = StringUtils.split(AclUtils.expandIP("1050::0005:akkg:300c:326b", 8), ":");
isScope = AclUtils.isIPv6Scope(adderss, 8);
Assert.assertFalse(isScope);
isScope = AclUtils.isIPv6Scope(adderss, 4);
Assert.assertTrue(isScope);
} }
@Test @Test
...@@ -102,6 +136,18 @@ public class AclUtilsTest { ...@@ -102,6 +136,18 @@ public class AclUtilsTest {
isScope = AclUtils.isScope(256); isScope = AclUtils.isScope(256);
Assert.assertFalse(isScope); Assert.assertFalse(isScope);
// IPv6 test
int min = Integer.parseInt("0", 16);
int max = Integer.parseInt("ffff", 16);
for (int i = min; i < max + 1; i++) {
isScope = AclUtils.isIPv6Scope(i);
Assert.assertTrue(isScope);
}
isScope = AclUtils.isIPv6Scope(-1);
Assert.assertFalse(isScope);
isScope = AclUtils.isIPv6Scope(max + 1);
Assert.assertFalse(isScope);
} }
@Test @Test
...@@ -115,10 +161,10 @@ public class AclUtilsTest { ...@@ -115,10 +161,10 @@ public class AclUtilsTest {
@Test @Test
public void isColonTest() { public void isColonTest() {
boolean isColon = AclUtils.isColon(","); boolean isColon = AclUtils.isComma(",");
Assert.assertTrue(isColon); Assert.assertTrue(isColon);
isColon = AclUtils.isColon("-"); isColon = AclUtils.isComma("-");
Assert.assertFalse(isColon); Assert.assertFalse(isColon);
} }
...@@ -131,6 +177,36 @@ public class AclUtilsTest { ...@@ -131,6 +177,36 @@ public class AclUtilsTest {
Assert.assertFalse(isMinus); Assert.assertFalse(isMinus);
} }
@Test
public void v6ipProcessTest() {
String remoteAddr = "5::7:6:1-200:*";
String[] strArray = StringUtils.split(remoteAddr, ":");
Assert.assertEquals(AclUtils.v6ipProcess(remoteAddr, strArray, 3), "0005:0000:0000:0000:0007:0006");
remoteAddr = "5::7:6:1-200";
strArray = StringUtils.split(remoteAddr, ":");
Assert.assertEquals(AclUtils.v6ipProcess(remoteAddr, strArray, 3), "0005:0000:0000:0000:0000:0007:0006");
remoteAddr = "5::7:6:*";
strArray = StringUtils.split(remoteAddr, ":");
Assert.assertEquals(AclUtils.v6ipProcess(remoteAddr, strArray, 3), "0005:0000:0000:0000:0000:0007:0006");
remoteAddr = "5:7:6:*";
strArray = StringUtils.split(remoteAddr, ":");
Assert.assertEquals(AclUtils.v6ipProcess(remoteAddr, strArray, 3), "0005:0007:0006");
}
@Test
public void expandIPTest() {
Assert.assertEquals(AclUtils.expandIP("::1", 8), "0000:0000:0000:0000:0000:0000:0000:0001");
Assert.assertEquals(AclUtils.expandIP("3::", 8), "0003:0000:0000:0000:0000:0000:0000:0000");
Assert.assertEquals(AclUtils.expandIP("2::2", 8), "0002:0000:0000:0000:0000:0000:0000:0002");
Assert.assertEquals(AclUtils.expandIP("4::aac4:92", 8), "0004:0000:0000:0000:0000:0000:AAC4:0092");
Assert.assertEquals(AclUtils.expandIP("ab23:56:901a::cc6:765:bb:9011", 8), "AB23:0056:901A:0000:0CC6:0765:00BB:9011");
Assert.assertEquals(AclUtils.expandIP("ab23:56:901a:1:cc6:765:bb:9011", 8), "AB23:0056:901A:0001:0CC6:0765:00BB:9011");
Assert.assertEquals(AclUtils.expandIP("5::7:6", 6), "0005:0000:0000:0000:0007:0006");
}
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@Test @Test
public void getYamlDataObjectTest() { public void getYamlDataObjectTest() {
...@@ -140,7 +216,7 @@ public class AclUtilsTest { ...@@ -140,7 +216,7 @@ public class AclUtilsTest {
} }
@Test @Test
public void writeDataObject2YamlFileTest() throws IOException{ public void writeDataObject2YamlFileTest() throws IOException {
String targetFileName = "src/test/resources/conf/plain_write_acl.yml"; String targetFileName = "src/test/resources/conf/plain_write_acl.yml";
File transport = new File(targetFileName); File transport = new File(targetFileName);
...@@ -153,7 +229,7 @@ public class AclUtilsTest { ...@@ -153,7 +229,7 @@ public class AclUtilsTest {
List<String> globalWhiteRemoteAddrs = new ArrayList<String>(); List<String> globalWhiteRemoteAddrs = new ArrayList<String>();
globalWhiteRemoteAddrs.add("10.10.103.*"); globalWhiteRemoteAddrs.add("10.10.103.*");
globalWhiteRemoteAddrs.add("192.168.0.*"); globalWhiteRemoteAddrs.add("192.168.0.*");
aclYamlMap.put("globalWhiteRemoteAddrs",globalWhiteRemoteAddrs); aclYamlMap.put("globalWhiteRemoteAddrs", globalWhiteRemoteAddrs);
// For accounts element in acl yaml config file // For accounts element in acl yaml config file
List<Map<String, Object>> accounts = new ArrayList<Map<String, Object>>(); List<Map<String, Object>> accounts = new ArrayList<Map<String, Object>>();
...@@ -166,14 +242,14 @@ public class AclUtilsTest { ...@@ -166,14 +242,14 @@ public class AclUtilsTest {
} }
}; };
accounts.add(accountsMap); accounts.add(accountsMap);
aclYamlMap.put("accounts",accounts); aclYamlMap.put("accounts", accounts);
Assert.assertTrue(AclUtils.writeDataObject(targetFileName, aclYamlMap)); Assert.assertTrue(AclUtils.writeDataObject(targetFileName, aclYamlMap));
transport.delete(); transport.delete();
} }
@Test @Test
public void updateExistedYamlFileTest() throws IOException{ public void updateExistedYamlFileTest() throws IOException {
String targetFileName = "src/test/resources/conf/plain_update_acl.yml"; String targetFileName = "src/test/resources/conf/plain_update_acl.yml";
File transport = new File(targetFileName); File transport = new File(targetFileName);
...@@ -186,7 +262,7 @@ public class AclUtilsTest { ...@@ -186,7 +262,7 @@ public class AclUtilsTest {
List<String> globalWhiteRemoteAddrs = new ArrayList<String>(); List<String> globalWhiteRemoteAddrs = new ArrayList<String>();
globalWhiteRemoteAddrs.add("10.10.103.*"); globalWhiteRemoteAddrs.add("10.10.103.*");
globalWhiteRemoteAddrs.add("192.168.0.*"); globalWhiteRemoteAddrs.add("192.168.0.*");
aclYamlMap.put("globalWhiteRemoteAddrs",globalWhiteRemoteAddrs); aclYamlMap.put("globalWhiteRemoteAddrs", globalWhiteRemoteAddrs);
// Write file to yaml file // Write file to yaml file
AclUtils.writeDataObject(targetFileName, aclYamlMap); AclUtils.writeDataObject(targetFileName, aclYamlMap);
...@@ -201,7 +277,7 @@ public class AclUtilsTest { ...@@ -201,7 +277,7 @@ public class AclUtilsTest {
Map<String, Object> readableMap = AclUtils.getYamlDataObject(targetFileName, Map.class); Map<String, Object> readableMap = AclUtils.getYamlDataObject(targetFileName, Map.class);
List<String> updatedGlobalWhiteRemoteAddrs = (List<String>) readableMap.get("globalWhiteRemoteAddrs"); List<String> updatedGlobalWhiteRemoteAddrs = (List<String>) readableMap.get("globalWhiteRemoteAddrs");
Assert.assertEquals("192.168.1.2",updatedGlobalWhiteRemoteAddrs.get(0)); Assert.assertEquals("192.168.1.2", updatedGlobalWhiteRemoteAddrs.get(0));
transport.delete(); transport.delete();
} }
...@@ -235,5 +311,4 @@ public class AclUtilsTest { ...@@ -235,5 +311,4 @@ public class AclUtilsTest {
Assert.assertNull(incompleteContRPCHook); Assert.assertNull(incompleteContRPCHook);
} }
} }
...@@ -29,6 +29,7 @@ import org.apache.rocketmq.acl.common.AclConstants; ...@@ -29,6 +29,7 @@ import org.apache.rocketmq.acl.common.AclConstants;
import org.apache.rocketmq.acl.common.AclException; import org.apache.rocketmq.acl.common.AclException;
import org.apache.rocketmq.acl.common.AclUtils; import org.apache.rocketmq.acl.common.AclUtils;
import org.apache.rocketmq.acl.common.SessionCredentials; import org.apache.rocketmq.acl.common.SessionCredentials;
import org.apache.rocketmq.common.AclConfig;
import org.apache.rocketmq.common.PlainAccessConfig; import org.apache.rocketmq.common.PlainAccessConfig;
import org.apache.rocketmq.common.protocol.RequestCode; import org.apache.rocketmq.common.protocol.RequestCode;
import org.apache.rocketmq.common.protocol.header.*; import org.apache.rocketmq.common.protocol.header.*;
...@@ -561,4 +562,12 @@ public class PlainAccessValidatorTest { ...@@ -561,4 +562,12 @@ public class PlainAccessValidatorTest {
AclUtils.writeDataObject(targetFileName, backUpAclConfigMap); AclUtils.writeDataObject(targetFileName, backUpAclConfigMap);
} }
@Test
public void getAllAclConfigTest(){
PlainAccessValidator plainAccessValidator = new PlainAccessValidator();
AclConfig aclConfig = plainAccessValidator.getAllAclConfig();
Assert.assertEquals(aclConfig.getGlobalWhiteAddrs().size(), 2);
Assert.assertEquals(aclConfig.getPlainAccessConfigs().size(), 2);
}
} }
...@@ -39,7 +39,7 @@ public class RemoteAddressStrategyTest { ...@@ -39,7 +39,7 @@ public class RemoteAddressStrategyTest {
plainAccessResource.setWhiteRemoteAddress("*"); plainAccessResource.setWhiteRemoteAddress("*");
RemoteAddressStrategy remoteAddressStrategy = remoteAddressStrategyFactory.getRemoteAddressStrategy(plainAccessResource); RemoteAddressStrategy remoteAddressStrategy = remoteAddressStrategyFactory.getRemoteAddressStrategy(plainAccessResource);
Assert.assertEquals(remoteAddressStrategy, RemoteAddressStrategyFactory.NULL_NET_ADDRESS_STRATEGY); Assert.assertEquals(remoteAddressStrategy, RemoteAddressStrategyFactory.NULL_NET_ADDRESS_STRATEGY);
plainAccessResource.setWhiteRemoteAddress("*.*.*.*"); plainAccessResource.setWhiteRemoteAddress("*.*.*.*");
remoteAddressStrategy = remoteAddressStrategyFactory.getRemoteAddressStrategy(plainAccessResource); remoteAddressStrategy = remoteAddressStrategyFactory.getRemoteAddressStrategy(plainAccessResource);
Assert.assertEquals(remoteAddressStrategy, RemoteAddressStrategyFactory.NULL_NET_ADDRESS_STRATEGY); Assert.assertEquals(remoteAddressStrategy, RemoteAddressStrategyFactory.NULL_NET_ADDRESS_STRATEGY);
...@@ -71,6 +71,35 @@ public class RemoteAddressStrategyTest { ...@@ -71,6 +71,35 @@ public class RemoteAddressStrategyTest {
plainAccessResource.setWhiteRemoteAddress(""); plainAccessResource.setWhiteRemoteAddress("");
remoteAddressStrategy = remoteAddressStrategyFactory.getRemoteAddressStrategy(plainAccessResource); remoteAddressStrategy = remoteAddressStrategyFactory.getRemoteAddressStrategy(plainAccessResource);
Assert.assertEquals(remoteAddressStrategy.getClass(), RemoteAddressStrategyFactory.BlankRemoteAddressStrategy.class); Assert.assertEquals(remoteAddressStrategy.getClass(), RemoteAddressStrategyFactory.BlankRemoteAddressStrategy.class);
// IPv6 test
plainAccessResource.setWhiteRemoteAddress("*:*:*:*:*:*:*:*");
remoteAddressStrategy = remoteAddressStrategyFactory.getRemoteAddressStrategy(plainAccessResource);
Assert.assertEquals(remoteAddressStrategy, RemoteAddressStrategyFactory.NULL_NET_ADDRESS_STRATEGY);
plainAccessResource.setWhiteRemoteAddress("1050:0000:0000:0000:0005:0600:300c:326b");
remoteAddressStrategy = remoteAddressStrategyFactory.getRemoteAddressStrategy(plainAccessResource);
Assert.assertEquals(remoteAddressStrategy.getClass(), RemoteAddressStrategyFactory.OneRemoteAddressStrategy.class);
plainAccessResource.setWhiteRemoteAddress("1050::0005:0600:300c:3261,1050::0005:0600:300c:3262,1050::0005:0600:300c:3263");
remoteAddressStrategy = remoteAddressStrategyFactory.getRemoteAddressStrategy(plainAccessResource);
Assert.assertEquals(remoteAddressStrategy.getClass(), RemoteAddressStrategyFactory.MultipleRemoteAddressStrategy.class);
plainAccessResource.setWhiteRemoteAddress("1050::0005:0600:300c:3261:{1,2,3}");
remoteAddressStrategy = remoteAddressStrategyFactory.getRemoteAddressStrategy(plainAccessResource);
Assert.assertEquals(remoteAddressStrategy.getClass(), RemoteAddressStrategyFactory.MultipleRemoteAddressStrategy.class);
plainAccessResource.setWhiteRemoteAddress("1050::0005:0600:300c:3261:1-200");
remoteAddressStrategy = remoteAddressStrategyFactory.getRemoteAddressStrategy(plainAccessResource);
Assert.assertEquals(remoteAddressStrategy.getClass(), RemoteAddressStrategyFactory.RangeRemoteAddressStrategy.class);
plainAccessResource.setWhiteRemoteAddress("1050:0005:0600:300c:3261:*");
remoteAddressStrategy = remoteAddressStrategyFactory.getRemoteAddressStrategy(plainAccessResource);
Assert.assertEquals(remoteAddressStrategy.getClass(), RemoteAddressStrategyFactory.RangeRemoteAddressStrategy.class);
plainAccessResource.setWhiteRemoteAddress("1050::0005:0600:300c:3261:1-20:*");
remoteAddressStrategy = remoteAddressStrategyFactory.getRemoteAddressStrategy(plainAccessResource);
Assert.assertEquals(remoteAddressStrategy.getClass(), RemoteAddressStrategyFactory.RangeRemoteAddressStrategy.class);
} }
@Test(expected = AclException.class) @Test(expected = AclException.class)
...@@ -80,6 +109,8 @@ public class RemoteAddressStrategyTest { ...@@ -80,6 +109,8 @@ public class RemoteAddressStrategyTest {
remoteAddressStrategyFactory.getRemoteAddressStrategy(plainAccessResource); remoteAddressStrategyFactory.getRemoteAddressStrategy(plainAccessResource);
plainAccessResource.setWhiteRemoteAddress("256.0.0.1"); plainAccessResource.setWhiteRemoteAddress("256.0.0.1");
remoteAddressStrategyFactory.getRemoteAddressStrategy(plainAccessResource); remoteAddressStrategyFactory.getRemoteAddressStrategy(plainAccessResource);
plainAccessResource.setWhiteRemoteAddress("::1ggg");
remoteAddressStrategyFactory.getRemoteAddressStrategy(plainAccessResource);
} }
@Test @Test
...@@ -94,6 +125,7 @@ public class RemoteAddressStrategyTest { ...@@ -94,6 +125,7 @@ public class RemoteAddressStrategyTest {
Assert.assertFalse(isMatch); Assert.assertFalse(isMatch);
} }
@Test
public void oneNetaddressStrategyTest() { public void oneNetaddressStrategyTest() {
PlainAccessResource plainAccessResource = new PlainAccessResource(); PlainAccessResource plainAccessResource = new PlainAccessResource();
plainAccessResource.setWhiteRemoteAddress("127.0.0.1"); plainAccessResource.setWhiteRemoteAddress("127.0.0.1");
...@@ -109,6 +141,26 @@ public class RemoteAddressStrategyTest { ...@@ -109,6 +141,26 @@ public class RemoteAddressStrategyTest {
plainAccessResource.setWhiteRemoteAddress("127.0.0.1"); plainAccessResource.setWhiteRemoteAddress("127.0.0.1");
match = remoteAddressStrategy.match(plainAccessResource); match = remoteAddressStrategy.match(plainAccessResource);
Assert.assertTrue(match); Assert.assertTrue(match);
// Ipv6 test
plainAccessResource = new PlainAccessResource();
plainAccessResource.setWhiteRemoteAddress("::1");
remoteAddressStrategy = remoteAddressStrategyFactory.getRemoteAddressStrategy(plainAccessResource);
plainAccessResource.setWhiteRemoteAddress("");
match = remoteAddressStrategy.match(plainAccessResource);
Assert.assertFalse(match);
plainAccessResource.setWhiteRemoteAddress("::2");
match = remoteAddressStrategy.match(plainAccessResource);
Assert.assertFalse(match);
plainAccessResource.setWhiteRemoteAddress("::1");
match = remoteAddressStrategy.match(plainAccessResource);
Assert.assertTrue(match);
plainAccessResource.setWhiteRemoteAddress("0000:0000:0000:0000:0000:0000:0000:0001");
match = remoteAddressStrategy.match(plainAccessResource);
Assert.assertTrue(match);
} }
@Test @Test
...@@ -122,6 +174,21 @@ public class RemoteAddressStrategyTest { ...@@ -122,6 +174,21 @@ public class RemoteAddressStrategyTest {
remoteAddressStrategy = remoteAddressStrategyFactory.getRemoteAddressStrategy(plainAccessResource); remoteAddressStrategy = remoteAddressStrategyFactory.getRemoteAddressStrategy(plainAccessResource);
multipleNetaddressStrategyTest(remoteAddressStrategy); multipleNetaddressStrategyTest(remoteAddressStrategy);
plainAccessResource.setWhiteRemoteAddress("192.100-150.*.*");
remoteAddressStrategy = remoteAddressStrategyFactory.getRemoteAddressStrategy(plainAccessResource);
plainAccessResource.setWhiteRemoteAddress("192.130.0.2");
boolean match = remoteAddressStrategy.match(plainAccessResource);
Assert.assertTrue(match);
plainAccessResource = new PlainAccessResource();
plainAccessResource.setWhiteRemoteAddress("1050::0005:0600:300c:1,1050::0005:0600:300c:2,1050::0005:0600:300c:3");
remoteAddressStrategy = remoteAddressStrategyFactory.getRemoteAddressStrategy(plainAccessResource);
multipleIPv6NetaddressStrategyTest(remoteAddressStrategy);
plainAccessResource.setWhiteRemoteAddress("1050::0005:0600:300c:{1,2,3}");
remoteAddressStrategy = remoteAddressStrategyFactory.getRemoteAddressStrategy(plainAccessResource);
multipleIPv6NetaddressStrategyTest(remoteAddressStrategy);
} }
@Test(expected = AclException.class) @Test(expected = AclException.class)
...@@ -129,6 +196,8 @@ public class RemoteAddressStrategyTest { ...@@ -129,6 +196,8 @@ public class RemoteAddressStrategyTest {
PlainAccessResource plainAccessResource = new PlainAccessResource(); PlainAccessResource plainAccessResource = new PlainAccessResource();
plainAccessResource.setWhiteRemoteAddress("127.0.0.1,2,3}"); plainAccessResource.setWhiteRemoteAddress("127.0.0.1,2,3}");
remoteAddressStrategyFactory.getRemoteAddressStrategy(plainAccessResource); remoteAddressStrategyFactory.getRemoteAddressStrategy(plainAccessResource);
plainAccessResource.setWhiteRemoteAddress("::1,2,3}");
remoteAddressStrategyFactory.getRemoteAddressStrategy(plainAccessResource);
} }
private void multipleNetaddressStrategyTest(RemoteAddressStrategy remoteAddressStrategy) { private void multipleNetaddressStrategyTest(RemoteAddressStrategy remoteAddressStrategy) {
...@@ -155,6 +224,30 @@ public class RemoteAddressStrategyTest { ...@@ -155,6 +224,30 @@ public class RemoteAddressStrategyTest {
} }
private void multipleIPv6NetaddressStrategyTest(RemoteAddressStrategy remoteAddressStrategy) {
PlainAccessResource plainAccessResource = new PlainAccessResource();
plainAccessResource.setWhiteRemoteAddress("1050:0000:0000:0000:0005:0600:300c:1");
boolean match = remoteAddressStrategy.match(plainAccessResource);
Assert.assertTrue(match);
plainAccessResource.setWhiteRemoteAddress("1050:0000:0000:0000:0005:0600:300c:2");
match = remoteAddressStrategy.match(plainAccessResource);
Assert.assertTrue(match);
plainAccessResource.setWhiteRemoteAddress("1050:0000:0000:0000:0005:0600:300c:3");
match = remoteAddressStrategy.match(plainAccessResource);
Assert.assertTrue(match);
plainAccessResource.setWhiteRemoteAddress("1050:0000:0000:0000:0005:0600:300c:4");
match = remoteAddressStrategy.match(plainAccessResource);
Assert.assertFalse(match);
plainAccessResource.setWhiteRemoteAddress("1050:0000:0000:0000:0005:0600:300c:0");
match = remoteAddressStrategy.match(plainAccessResource);
Assert.assertFalse(match);
}
@Test @Test
public void rangeNetaddressStrategyTest() { public void rangeNetaddressStrategyTest() {
String head = "127.0.0."; String head = "127.0.0.";
...@@ -162,6 +255,7 @@ public class RemoteAddressStrategyTest { ...@@ -162,6 +255,7 @@ public class RemoteAddressStrategyTest {
plainAccessResource.setWhiteRemoteAddress("127.0.0.1-200"); plainAccessResource.setWhiteRemoteAddress("127.0.0.1-200");
RemoteAddressStrategy remoteAddressStrategy = remoteAddressStrategyFactory.getRemoteAddressStrategy(plainAccessResource); RemoteAddressStrategy remoteAddressStrategy = remoteAddressStrategyFactory.getRemoteAddressStrategy(plainAccessResource);
rangeNetaddressStrategyTest(remoteAddressStrategy, head, 1, 200, true); rangeNetaddressStrategyTest(remoteAddressStrategy, head, 1, 200, true);
plainAccessResource.setWhiteRemoteAddress("127.0.0.*"); plainAccessResource.setWhiteRemoteAddress("127.0.0.*");
remoteAddressStrategy = remoteAddressStrategyFactory.getRemoteAddressStrategy(plainAccessResource); remoteAddressStrategy = remoteAddressStrategyFactory.getRemoteAddressStrategy(plainAccessResource);
rangeNetaddressStrategyTest(remoteAddressStrategy, head, 0, 255, true); rangeNetaddressStrategyTest(remoteAddressStrategy, head, 0, 255, true);
...@@ -169,14 +263,40 @@ public class RemoteAddressStrategyTest { ...@@ -169,14 +263,40 @@ public class RemoteAddressStrategyTest {
plainAccessResource.setWhiteRemoteAddress("127.0.1-200.*"); plainAccessResource.setWhiteRemoteAddress("127.0.1-200.*");
remoteAddressStrategy = remoteAddressStrategyFactory.getRemoteAddressStrategy(plainAccessResource); remoteAddressStrategy = remoteAddressStrategyFactory.getRemoteAddressStrategy(plainAccessResource);
rangeNetaddressStrategyThirdlyTest(remoteAddressStrategy, head, 1, 200); rangeNetaddressStrategyThirdlyTest(remoteAddressStrategy, head, 1, 200);
plainAccessResource.setWhiteRemoteAddress("127.*.*.*"); plainAccessResource.setWhiteRemoteAddress("127.*.*.*");
remoteAddressStrategy = remoteAddressStrategyFactory.getRemoteAddressStrategy(plainAccessResource); remoteAddressStrategy = remoteAddressStrategyFactory.getRemoteAddressStrategy(plainAccessResource);
rangeNetaddressStrategyThirdlyTest(remoteAddressStrategy, head, 1, 200); rangeNetaddressStrategyTest(remoteAddressStrategy, head, 0, 255, true);
plainAccessResource.setWhiteRemoteAddress("127.1-150.*.*"); plainAccessResource.setWhiteRemoteAddress("127.1-150.*.*");
remoteAddressStrategy = remoteAddressStrategyFactory.getRemoteAddressStrategy(plainAccessResource); remoteAddressStrategy = remoteAddressStrategyFactory.getRemoteAddressStrategy(plainAccessResource);
rangeNetaddressStrategyThirdlyTest(remoteAddressStrategy, head, 1, 200); rangeNetaddressStrategyThirdlyTest(remoteAddressStrategy, head, 1, 200);
// IPv6 test
head = "1050::0005:0600:300c:";
plainAccessResource = new PlainAccessResource();
plainAccessResource.setWhiteRemoteAddress("1050::0005:0600:300c:1-200");
remoteAddressStrategy = remoteAddressStrategyFactory.getRemoteAddressStrategy(plainAccessResource);
rangeIPv6NetaddressStrategyTest(remoteAddressStrategy, head, "1", "200", true);
plainAccessResource.setWhiteRemoteAddress("1050::0005:0600:300c:*");
remoteAddressStrategy = remoteAddressStrategyFactory.getRemoteAddressStrategy(plainAccessResource);
rangeIPv6NetaddressStrategyTest(remoteAddressStrategy, head, "0", "ffff", true);
plainAccessResource.setWhiteRemoteAddress("1050::0005:0600:3001:*");
remoteAddressStrategy = remoteAddressStrategyFactory.getRemoteAddressStrategy(plainAccessResource);
rangeIPv6NetaddressStrategyTest(remoteAddressStrategy, head, "0", "ffff", false);
head = "1050::0005:0600:300c:1:";
plainAccessResource.setWhiteRemoteAddress("1050::0005:0600:300c:1-200:*");
remoteAddressStrategy = remoteAddressStrategyFactory.getRemoteAddressStrategy(plainAccessResource);
rangeIPv6NetaddressStrategyTest(remoteAddressStrategy, head, "0", "ffff", true);
head = "1050::0005:0600:300c:201:";
plainAccessResource.setWhiteRemoteAddress("1050::0005:0600:300c:1-200:*");
remoteAddressStrategy = remoteAddressStrategyFactory.getRemoteAddressStrategy(plainAccessResource);
rangeIPv6NetaddressStrategyTest(remoteAddressStrategy, head, "0", "ffff", false);
} }
private void rangeNetaddressStrategyTest(RemoteAddressStrategy remoteAddressStrategy, String head, int start, private void rangeNetaddressStrategyTest(RemoteAddressStrategy remoteAddressStrategy, String head, int start,
...@@ -206,6 +326,25 @@ public class RemoteAddressStrategyTest { ...@@ -206,6 +326,25 @@ public class RemoteAddressStrategyTest {
} }
} }
private void rangeIPv6NetaddressStrategyTest(RemoteAddressStrategy remoteAddressStrategy, String head, String start,
String end,
boolean isFalse) {
PlainAccessResource plainAccessResource = new PlainAccessResource();
for (int i = -10; i < 65536 + 100; i++) {
String hex = Integer.toHexString(i);
plainAccessResource.setWhiteRemoteAddress(head + hex);
boolean match = remoteAddressStrategy.match(plainAccessResource);
int startNum = Integer.parseInt(start, 16);
int endNum = Integer.parseInt(end, 16);
if (isFalse && i >= startNum && i <= endNum) {
Assert.assertTrue(match);
continue;
}
Assert.assertFalse(match);
}
}
@Test(expected = AclException.class) @Test(expected = AclException.class)
public void rangeNetaddressStrategyExceptionStartGreaterEndTest() { public void rangeNetaddressStrategyExceptionStartGreaterEndTest() {
rangeNetaddressStrategyExceptionTest("127.0.0.2-1"); rangeNetaddressStrategyExceptionTest("127.0.0.2-1");
......
...@@ -166,7 +166,7 @@ public class BrokerController { ...@@ -166,7 +166,7 @@ public class BrokerController {
private TransactionalMessageService transactionalMessageService; private TransactionalMessageService transactionalMessageService;
private AbstractTransactionalMessageCheckListener transactionalMessageCheckListener; private AbstractTransactionalMessageCheckListener transactionalMessageCheckListener;
private Future<?> slaveSyncFuture; private Future<?> slaveSyncFuture;
private Map<Class, AccessValidator> accessValidatorMap = new HashMap<Class, AccessValidator>(); private Map<Class,AccessValidator> accessValidatorMap = new HashMap<Class, AccessValidator>();
public BrokerController( public BrokerController(
final BrokerConfig brokerConfig, final BrokerConfig brokerConfig,
...@@ -245,7 +245,7 @@ public class BrokerController { ...@@ -245,7 +245,7 @@ public class BrokerController {
this.brokerConfig); this.brokerConfig);
if (messageStoreConfig.isEnableDLegerCommitLog()) { if (messageStoreConfig.isEnableDLegerCommitLog()) {
DLedgerRoleChangeHandler roleChangeHandler = new DLedgerRoleChangeHandler(this, (DefaultMessageStore) messageStore); DLedgerRoleChangeHandler roleChangeHandler = new DLedgerRoleChangeHandler(this, (DefaultMessageStore) messageStore);
((DLedgerCommitLog) ((DefaultMessageStore) messageStore).getCommitLog()).getdLedgerServer().getdLedgerLeaderElector().addRoleChangeHandler(roleChangeHandler); ((DLedgerCommitLog)((DefaultMessageStore) messageStore).getCommitLog()).getdLedgerServer().getdLedgerLeaderElector().addRoleChangeHandler(roleChangeHandler);
} }
this.brokerStats = new BrokerStats((DefaultMessageStore) this.messageStore); this.brokerStats = new BrokerStats((DefaultMessageStore) this.messageStore);
//load plugin //load plugin
...@@ -513,9 +513,9 @@ public class BrokerController { ...@@ -513,9 +513,9 @@ public class BrokerController {
return; return;
} }
for (AccessValidator accessValidator : accessValidators) { for (AccessValidator accessValidator: accessValidators) {
final AccessValidator validator = accessValidator; final AccessValidator validator = accessValidator;
accessValidatorMap.put(validator.getClass(), validator); accessValidatorMap.put(validator.getClass(),validator);
this.registerServerRPCHook(new RPCHook() { this.registerServerRPCHook(new RPCHook() {
@Override @Override
...@@ -531,13 +531,14 @@ public class BrokerController { ...@@ -531,13 +531,14 @@ public class BrokerController {
} }
} }
private void initialRpcHooks() { private void initialRpcHooks() {
List<RPCHook> rpcHooks = ServiceProvider.load(ServiceProvider.RPC_HOOK_ID, RPCHook.class); List<RPCHook> rpcHooks = ServiceProvider.load(ServiceProvider.RPC_HOOK_ID, RPCHook.class);
if (rpcHooks == null || rpcHooks.isEmpty()) { if (rpcHooks == null || rpcHooks.isEmpty()) {
return; return;
} }
for (RPCHook rpcHook : rpcHooks) { for (RPCHook rpcHook: rpcHooks) {
this.registerServerRPCHook(rpcHook); this.registerServerRPCHook(rpcHook);
} }
} }
...@@ -883,10 +884,9 @@ public class BrokerController { ...@@ -883,10 +884,9 @@ public class BrokerController {
if (!messageStoreConfig.isEnableDLegerCommitLog()) { if (!messageStoreConfig.isEnableDLegerCommitLog()) {
startProcessorByHa(messageStoreConfig.getBrokerRole()); startProcessorByHa(messageStoreConfig.getBrokerRole());
handleSlaveSynchronize(messageStoreConfig.getBrokerRole()); handleSlaveSynchronize(messageStoreConfig.getBrokerRole());
this.registerBrokerAll(true, false, true);
} }
this.registerBrokerAll(true, false, true);
this.scheduledExecutorService.scheduleAtFixedRate(new Runnable() { this.scheduledExecutorService.scheduleAtFixedRate(new Runnable() {
@Override @Override
...@@ -907,6 +907,7 @@ public class BrokerController { ...@@ -907,6 +907,7 @@ public class BrokerController {
this.brokerFastFailure.start(); this.brokerFastFailure.start();
} }
} }
public synchronized void registerIncrementBrokerData(TopicConfig topicConfig, DataVersion dataVersion) { public synchronized void registerIncrementBrokerData(TopicConfig topicConfig, DataVersion dataVersion) {
...@@ -1120,6 +1121,7 @@ public class BrokerController { ...@@ -1120,6 +1121,7 @@ public class BrokerController {
this.transactionalMessageCheckListener = transactionalMessageCheckListener; this.transactionalMessageCheckListener = transactionalMessageCheckListener;
} }
public BlockingQueue<Runnable> getEndTransactionThreadPoolQueue() { public BlockingQueue<Runnable> getEndTransactionThreadPoolQueue() {
return endTransactionThreadPoolQueue; return endTransactionThreadPoolQueue;
...@@ -1140,7 +1142,8 @@ public class BrokerController { ...@@ -1140,7 +1142,8 @@ public class BrokerController {
public void run() { public void run() {
try { try {
BrokerController.this.slaveSynchronize.syncAll(); BrokerController.this.slaveSynchronize.syncAll();
} catch (Throwable e) { }
catch (Throwable e) {
log.error("ScheduledTask SlaveSynchronize syncAll error.", e); log.error("ScheduledTask SlaveSynchronize syncAll error.", e);
} }
} }
...@@ -1186,6 +1189,8 @@ public class BrokerController { ...@@ -1186,6 +1189,8 @@ public class BrokerController {
log.info("Finish to change to slave brokerName={} brokerId={}", brokerConfig.getBrokerName(), brokerId); log.info("Finish to change to slave brokerName={} brokerId={}", brokerConfig.getBrokerName(), brokerId);
} }
public void changeToMaster(BrokerRole role) { public void changeToMaster(BrokerRole role) {
if (role == BrokerRole.SLAVE) { if (role == BrokerRole.SLAVE) {
return; return;
...@@ -1235,4 +1240,6 @@ public class BrokerController { ...@@ -1235,4 +1240,6 @@ public class BrokerController {
} }
} }
} }
...@@ -178,6 +178,10 @@ public class BrokerStartup { ...@@ -178,6 +178,10 @@ public class BrokerStartup {
break; break;
} }
if (messageStoreConfig.isEnableDLegerCommitLog()) {
brokerConfig.setBrokerId(-1);
}
messageStoreConfig.setHaListenPort(nettyServerConfig.getListenPort() + 1); messageStoreConfig.setHaListenPort(nettyServerConfig.getListenPort() + 1);
LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory(); LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();
JoranConfigurator configurator = new JoranConfigurator(); JoranConfigurator configurator = new JoranConfigurator();
......
...@@ -42,6 +42,7 @@ import org.apache.rocketmq.common.MQVersion; ...@@ -42,6 +42,7 @@ import org.apache.rocketmq.common.MQVersion;
import org.apache.rocketmq.common.MixAll; import org.apache.rocketmq.common.MixAll;
import org.apache.rocketmq.common.PlainAccessConfig; import org.apache.rocketmq.common.PlainAccessConfig;
import org.apache.rocketmq.common.TopicConfig; import org.apache.rocketmq.common.TopicConfig;
import org.apache.rocketmq.common.AclConfig;
import org.apache.rocketmq.common.UtilAll; import org.apache.rocketmq.common.UtilAll;
import org.apache.rocketmq.common.admin.ConsumeStats; import org.apache.rocketmq.common.admin.ConsumeStats;
import org.apache.rocketmq.common.admin.OffsetWrapper; import org.apache.rocketmq.common.admin.OffsetWrapper;
...@@ -52,6 +53,8 @@ import org.apache.rocketmq.common.protocol.header.CreateAccessConfigRequestHeade ...@@ -52,6 +53,8 @@ import org.apache.rocketmq.common.protocol.header.CreateAccessConfigRequestHeade
import org.apache.rocketmq.common.protocol.header.DeleteAccessConfigRequestHeader; import org.apache.rocketmq.common.protocol.header.DeleteAccessConfigRequestHeader;
import org.apache.rocketmq.common.protocol.header.GetBrokerAclConfigResponseHeader; import org.apache.rocketmq.common.protocol.header.GetBrokerAclConfigResponseHeader;
import org.apache.rocketmq.common.protocol.header.UpdateGlobalWhiteAddrsConfigRequestHeader; import org.apache.rocketmq.common.protocol.header.UpdateGlobalWhiteAddrsConfigRequestHeader;
import org.apache.rocketmq.common.protocol.header.GetBrokerClusterAclConfigResponseHeader;
import org.apache.rocketmq.common.protocol.header.GetBrokerClusterAclConfigResponseBody;
import org.apache.rocketmq.logging.InternalLogger; import org.apache.rocketmq.logging.InternalLogger;
import org.apache.rocketmq.logging.InternalLoggerFactory; import org.apache.rocketmq.logging.InternalLoggerFactory;
import org.apache.rocketmq.common.message.MessageAccessor; import org.apache.rocketmq.common.message.MessageAccessor;
...@@ -226,6 +229,8 @@ public class AdminBrokerProcessor implements NettyRequestProcessor { ...@@ -226,6 +229,8 @@ public class AdminBrokerProcessor implements NettyRequestProcessor {
return updateGlobalWhiteAddrsConfig(ctx, request); return updateGlobalWhiteAddrsConfig(ctx, request);
case RequestCode.RESUME_CHECK_HALF_MESSAGE: case RequestCode.RESUME_CHECK_HALF_MESSAGE:
return resumeCheckHalfMessage(ctx, request); return resumeCheckHalfMessage(ctx, request);
case RequestCode.GET_BROKER_CLUSTER_ACL_CONFIG:
return getBrokerClusterAclConfig(ctx, request);
default: default:
break; break;
} }
...@@ -428,6 +433,27 @@ public class AdminBrokerProcessor implements NettyRequestProcessor { ...@@ -428,6 +433,27 @@ public class AdminBrokerProcessor implements NettyRequestProcessor {
return null; return null;
} }
private RemotingCommand getBrokerClusterAclConfig(ChannelHandlerContext ctx, RemotingCommand request) {
final RemotingCommand response = RemotingCommand.createResponseCommand(GetBrokerClusterAclConfigResponseHeader.class);
try {
AccessValidator accessValidator = this.brokerController.getAccessValidatorMap().get(PlainAccessValidator.class);
GetBrokerClusterAclConfigResponseBody body = new GetBrokerClusterAclConfigResponseBody();
AclConfig aclConfig = accessValidator.getAllAclConfig();
body.setGlobalWhiteAddrs(aclConfig.getGlobalWhiteAddrs());
body.setPlainAccessConfigs(aclConfig.getPlainAccessConfigs());
response.setCode(ResponseCode.SUCCESS);
response.setBody(body.encode());
response.setRemark(null);
return response;
} catch (Exception e) {
log.error("Failed to generate a proper getBrokerClusterAclConfig response", e);
}
return null;
}
private RemotingCommand getAllTopicConfig(ChannelHandlerContext ctx, RemotingCommand request) { private RemotingCommand getAllTopicConfig(ChannelHandlerContext ctx, RemotingCommand request) {
final RemotingCommand response = RemotingCommand.createResponseCommand(GetAllTopicConfigResponseHeader.class); final RemotingCommand response = RemotingCommand.createResponseCommand(GetAllTopicConfigResponseHeader.class);
// final GetAllTopicConfigResponseHeader responseHeader = // final GetAllTopicConfigResponseHeader responseHeader =
......
...@@ -41,8 +41,6 @@ import org.apache.rocketmq.common.constant.PermName; ...@@ -41,8 +41,6 @@ import org.apache.rocketmq.common.constant.PermName;
import org.apache.rocketmq.common.filter.ExpressionType; import org.apache.rocketmq.common.filter.ExpressionType;
import org.apache.rocketmq.common.filter.FilterAPI; import org.apache.rocketmq.common.filter.FilterAPI;
import org.apache.rocketmq.common.help.FAQUrl; import org.apache.rocketmq.common.help.FAQUrl;
import org.apache.rocketmq.logging.InternalLogger;
import org.apache.rocketmq.logging.InternalLoggerFactory;
import org.apache.rocketmq.common.message.MessageDecoder; import org.apache.rocketmq.common.message.MessageDecoder;
import org.apache.rocketmq.common.message.MessageQueue; import org.apache.rocketmq.common.message.MessageQueue;
import org.apache.rocketmq.common.protocol.ResponseCode; import org.apache.rocketmq.common.protocol.ResponseCode;
...@@ -52,7 +50,10 @@ import org.apache.rocketmq.common.protocol.heartbeat.MessageModel; ...@@ -52,7 +50,10 @@ import org.apache.rocketmq.common.protocol.heartbeat.MessageModel;
import org.apache.rocketmq.common.protocol.heartbeat.SubscriptionData; import org.apache.rocketmq.common.protocol.heartbeat.SubscriptionData;
import org.apache.rocketmq.common.protocol.topic.OffsetMovedEvent; import org.apache.rocketmq.common.protocol.topic.OffsetMovedEvent;
import org.apache.rocketmq.common.subscription.SubscriptionGroupConfig; 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.sysflag.PullSysFlag;
import org.apache.rocketmq.logging.InternalLogger;
import org.apache.rocketmq.logging.InternalLoggerFactory;
import org.apache.rocketmq.remoting.common.RemotingHelper; import org.apache.rocketmq.remoting.common.RemotingHelper;
import org.apache.rocketmq.remoting.common.RemotingUtil; import org.apache.rocketmq.remoting.common.RemotingUtil;
import org.apache.rocketmq.remoting.exception.RemotingCommandException; import org.apache.rocketmq.remoting.exception.RemotingCommandException;
...@@ -494,7 +495,21 @@ public class PullMessageProcessor implements NettyRequestProcessor { ...@@ -494,7 +495,21 @@ public class PullMessageProcessor implements NettyRequestProcessor {
for (ByteBuffer bb : messageBufferList) { for (ByteBuffer bb : messageBufferList) {
byteBuffer.put(bb); byteBuffer.put(bb);
storeTimestamp = bb.getLong(MessageDecoder.MESSAGE_STORE_TIMESTAMP_POSTION); int sysFlag = bb.getInt(MessageDecoder.SYSFLAG_POSITION);
// bornhost has the IPv4 ip if the MessageSysFlag.BORNHOST_V6_FLAG bit of sysFlag is 0
// IPv4 host = ip(4 byte) + port(4 byte); IPv6 host = ip(16 byte) + port(4 byte)
int bornhostLength = (sysFlag & MessageSysFlag.BORNHOST_V6_FLAG) == 0 ? 8 : 20;
int msgStoreTimePos = 4 // 1 TOTALSIZE
+ 4 // 2 MAGICCODE
+ 4 // 3 BODYCRC
+ 4 // 4 QUEUEID
+ 4 // 5 FLAG
+ 8 // 6 QUEUEOFFSET
+ 8 // 7 PHYSICALOFFSET
+ 4 // 8 SYSFLAG
+ 8 // 9 BORNTIMESTAMP
+ bornhostLength; // 10 BORNHOST
storeTimestamp = bb.getLong(msgStoreTimePos);
} }
} finally { } finally {
getMessageResult.release(); getMessageResult.release();
......
...@@ -48,6 +48,7 @@ import org.apache.rocketmq.common.MQVersion; ...@@ -48,6 +48,7 @@ import org.apache.rocketmq.common.MQVersion;
import org.apache.rocketmq.common.MixAll; import org.apache.rocketmq.common.MixAll;
import org.apache.rocketmq.common.PlainAccessConfig; import org.apache.rocketmq.common.PlainAccessConfig;
import org.apache.rocketmq.common.TopicConfig; import org.apache.rocketmq.common.TopicConfig;
import org.apache.rocketmq.common.AclConfig;
import org.apache.rocketmq.common.UtilAll; import org.apache.rocketmq.common.UtilAll;
import org.apache.rocketmq.common.admin.ConsumeStats; import org.apache.rocketmq.common.admin.ConsumeStats;
import org.apache.rocketmq.common.admin.TopicStatsTable; import org.apache.rocketmq.common.admin.TopicStatsTable;
...@@ -95,6 +96,7 @@ import org.apache.rocketmq.common.protocol.header.DeleteSubscriptionGroupRequest ...@@ -95,6 +96,7 @@ import org.apache.rocketmq.common.protocol.header.DeleteSubscriptionGroupRequest
import org.apache.rocketmq.common.protocol.header.DeleteTopicRequestHeader; import org.apache.rocketmq.common.protocol.header.DeleteTopicRequestHeader;
import org.apache.rocketmq.common.protocol.header.EndTransactionRequestHeader; import org.apache.rocketmq.common.protocol.header.EndTransactionRequestHeader;
import org.apache.rocketmq.common.protocol.header.GetBrokerAclConfigResponseHeader; import org.apache.rocketmq.common.protocol.header.GetBrokerAclConfigResponseHeader;
import org.apache.rocketmq.common.protocol.header.GetBrokerClusterAclConfigResponseBody;
import org.apache.rocketmq.common.protocol.header.GetConsumeStatsInBrokerHeader; import org.apache.rocketmq.common.protocol.header.GetConsumeStatsInBrokerHeader;
import org.apache.rocketmq.common.protocol.header.GetConsumeStatsRequestHeader; import org.apache.rocketmq.common.protocol.header.GetConsumeStatsRequestHeader;
import org.apache.rocketmq.common.protocol.header.GetConsumerConnectionListRequestHeader; import org.apache.rocketmq.common.protocol.header.GetConsumerConnectionListRequestHeader;
...@@ -392,6 +394,30 @@ public class MQClientAPIImpl { ...@@ -392,6 +394,30 @@ public class MQClientAPIImpl {
} }
public AclConfig getBrokerClusterConfig(final String addr, final long timeoutMillis) throws RemotingCommandException, InterruptedException, RemotingTimeoutException,
RemotingSendRequestException, RemotingConnectException, MQBrokerException {
RemotingCommand request = RemotingCommand.createRequestCommand(RequestCode.GET_BROKER_CLUSTER_ACL_CONFIG, null);
RemotingCommand response = this.remotingClient.invokeSync(MixAll.brokerVIPChannel(this.clientConfig.isVipChannelEnabled(), addr), request, timeoutMillis);
assert response != null;
switch (response.getCode()) {
case ResponseCode.SUCCESS: {
if (response.getBody() != null) {
GetBrokerClusterAclConfigResponseBody body =
GetBrokerClusterAclConfigResponseBody.decode(response.getBody(), GetBrokerClusterAclConfigResponseBody.class);
AclConfig aclConfig = new AclConfig();
aclConfig.setGlobalWhiteAddrs(body.getGlobalWhiteAddrs());
aclConfig.setPlainAccessConfigs(body.getPlainAccessConfigs());
return aclConfig;
}
}
default:
break;
}
throw new MQBrokerException(response.getCode(), response.getRemark());
}
public SendResult sendMessage( public SendResult sendMessage(
final String addr, final String addr,
final String brokerName, final String brokerName,
......
...@@ -1205,6 +1205,12 @@ public class DefaultMQProducerImpl implements MQProducerInner { ...@@ -1205,6 +1205,12 @@ public class DefaultMQProducerImpl implements MQProducerInner {
if (null == localTransactionExecuter && null == transactionListener) { if (null == localTransactionExecuter && null == transactionListener) {
throw new MQClientException("tranExecutor is null", null); throw new MQClientException("tranExecutor is null", null);
} }
// ignore DelayTimeLevel parameter
if (msg.getDelayTimeLevel() != 0) {
MessageAccessor.clearProperty(msg, MessageConst.PROPERTY_DELAY_TIME_LEVEL);
}
Validators.checkMessage(msg, this.defaultMQProducer); Validators.checkMessage(msg, this.defaultMQProducer);
SendResult sendResult = null; SendResult sendResult = null;
......
...@@ -216,7 +216,11 @@ public class AsyncTraceDispatcher implements TraceDispatcher { ...@@ -216,7 +216,11 @@ public class AsyncTraceDispatcher implements TraceDispatcher {
public void removeShutdownHook() { public void removeShutdownHook() {
if (shutDownHook != null) { if (shutDownHook != null) {
Runtime.getRuntime().removeShutdownHook(shutDownHook); try {
Runtime.getRuntime().removeShutdownHook(shutDownHook);
} catch (IllegalStateException e) {
// ignore - VM is already shutting down
}
} }
} }
......
...@@ -56,7 +56,9 @@ import org.junit.Test; ...@@ -56,7 +56,9 @@ import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.mockito.Mock; import org.mockito.Mock;
import org.mockito.Spy; import org.mockito.Spy;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.junit.MockitoJUnitRunner; import org.mockito.junit.MockitoJUnitRunner;
import org.mockito.stubbing.Answer;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Fail.failBecauseExceptionWasNotThrown; import static org.assertj.core.api.Fail.failBecauseExceptionWasNotThrown;
...@@ -109,7 +111,22 @@ public class DefaultMQProducerTest { ...@@ -109,7 +111,22 @@ public class DefaultMQProducerTest {
nullable(SendMessageContext.class), any(DefaultMQProducerImpl.class))).thenCallRealMethod(); nullable(SendMessageContext.class), any(DefaultMQProducerImpl.class))).thenCallRealMethod();
when(mQClientAPIImpl.sendMessage(anyString(), anyString(), any(Message.class), any(SendMessageRequestHeader.class), anyLong(), any(CommunicationMode.class), when(mQClientAPIImpl.sendMessage(anyString(), anyString(), any(Message.class), any(SendMessageRequestHeader.class), anyLong(), any(CommunicationMode.class),
nullable(SendCallback.class), nullable(TopicPublishInfo.class), nullable(MQClientInstance.class), anyInt(), nullable(SendMessageContext.class), any(DefaultMQProducerImpl.class))) nullable(SendCallback.class), nullable(TopicPublishInfo.class), nullable(MQClientInstance.class), anyInt(), nullable(SendMessageContext.class), any(DefaultMQProducerImpl.class)))
.thenReturn(createSendResult(SendStatus.SEND_OK)); .thenAnswer(new Answer() {
@Override
public Object answer(InvocationOnMock invocation) throws Throwable {
CommunicationMode mode = invocation.getArgument(5);
switch (mode) {
case SYNC:
return createSendResult(SendStatus.SEND_OK);
case ONEWAY:
case ASYNC:
SendCallback callback = invocation.getArgument(6);
callback.onSuccess(createSendResult(SendStatus.SEND_OK));
return null;
}
return null;
}
});
} }
@After @After
...@@ -172,6 +189,8 @@ public class DefaultMQProducerTest { ...@@ -172,6 +189,8 @@ public class DefaultMQProducerTest {
@Test @Test
public void testSendMessageAsync_Success() throws RemotingException, InterruptedException, MQBrokerException, MQClientException { public void testSendMessageAsync_Success() throws RemotingException, InterruptedException, MQBrokerException, MQClientException {
final CountDownLatch countDownLatch = new CountDownLatch(1); final CountDownLatch countDownLatch = new CountDownLatch(1);
// final AtomicInteger cc = new AtomicInteger(0);
when(mQClientAPIImpl.getTopicRouteInfoFromNameServer(anyString(), anyLong())).thenReturn(createTopicRoute());
producer.send(message, new SendCallback() { producer.send(message, new SendCallback() {
@Override @Override
public void onSuccess(SendResult sendResult) { public void onSuccess(SendResult sendResult) {
...@@ -179,14 +198,15 @@ public class DefaultMQProducerTest { ...@@ -179,14 +198,15 @@ public class DefaultMQProducerTest {
assertThat(sendResult.getOffsetMsgId()).isEqualTo("123"); assertThat(sendResult.getOffsetMsgId()).isEqualTo("123");
assertThat(sendResult.getQueueOffset()).isEqualTo(456L); assertThat(sendResult.getQueueOffset()).isEqualTo(456L);
countDownLatch.countDown(); countDownLatch.countDown();
// cc.incrementAndGet();
} }
@Override @Override
public void onException(Throwable e) { public void onException(Throwable e) {
countDownLatch.countDown();
} }
}); });
countDownLatch.await(3000L, TimeUnit.MILLISECONDS); countDownLatch.await(3000L, TimeUnit.MILLISECONDS);
// assertThat(cc.get()).isEqualTo(1);
} }
@Test @Test
...@@ -194,9 +214,11 @@ public class DefaultMQProducerTest { ...@@ -194,9 +214,11 @@ public class DefaultMQProducerTest {
final AtomicInteger cc = new AtomicInteger(0); final AtomicInteger cc = new AtomicInteger(0);
final CountDownLatch countDownLatch = new CountDownLatch(6); final CountDownLatch countDownLatch = new CountDownLatch(6);
when(mQClientAPIImpl.getTopicRouteInfoFromNameServer(anyString(), anyLong())).thenReturn(createTopicRoute());
SendCallback sendCallback = new SendCallback() { SendCallback sendCallback = new SendCallback() {
@Override @Override
public void onSuccess(SendResult sendResult) { public void onSuccess(SendResult sendResult) {
countDownLatch.countDown();
} }
@Override @Override
...@@ -217,35 +239,38 @@ public class DefaultMQProducerTest { ...@@ -217,35 +239,38 @@ public class DefaultMQProducerTest {
message.setTopic("test"); message.setTopic("test");
message.setBody("hello world".getBytes()); message.setBody("hello world".getBytes());
producer.send(new Message(), sendCallback); producer.send(new Message(), sendCallback);
producer.send(message, sendCallback, 1000);
producer.send(message, new MessageQueue(), sendCallback); producer.send(message, new MessageQueue(), sendCallback);
producer.send(new Message(), new MessageQueue(), sendCallback, 1000); producer.send(new Message(), new MessageQueue(), sendCallback, 1000);
producer.send(new Message(), messageQueueSelector, null, sendCallback); producer.send(new Message(), messageQueueSelector, null, sendCallback);
producer.send(message, messageQueueSelector, null, sendCallback, 1000); producer.send(message, messageQueueSelector, null, sendCallback, 1000);
//this message is send success
producer.send(message, sendCallback, 1000);
countDownLatch.await(3000L, TimeUnit.MILLISECONDS); countDownLatch.await(3000L, TimeUnit.MILLISECONDS);
assertThat(cc.get()).isEqualTo(6); assertThat(cc.get()).isEqualTo(5);
} }
@Test @Test
public void testSendMessageAsync_BodyCompressed() throws RemotingException, InterruptedException, MQBrokerException, MQClientException { public void testSendMessageAsync_BodyCompressed() throws RemotingException, InterruptedException, MQBrokerException, MQClientException {
final AtomicInteger cc = new AtomicInteger(0);
final CountDownLatch countDownLatch = new CountDownLatch(1); final CountDownLatch countDownLatch = new CountDownLatch(1);
when(mQClientAPIImpl.getTopicRouteInfoFromNameServer(anyString(), anyLong())).thenReturn(createTopicRoute());
producer.send(bigMessage, new SendCallback() { producer.send(bigMessage, new SendCallback() {
@Override @Override
public void onSuccess(SendResult sendResult) { public void onSuccess(SendResult sendResult) {
assertThat(sendResult.getSendStatus()).isEqualTo(SendStatus.SEND_OK); assertThat(sendResult.getSendStatus()).isEqualTo(SendStatus.SEND_OK);
assertThat(sendResult.getOffsetMsgId()).isEqualTo("123"); assertThat(sendResult.getOffsetMsgId()).isEqualTo("123");
assertThat(sendResult.getQueueOffset()).isEqualTo(456L); assertThat(sendResult.getQueueOffset()).isEqualTo(456L);
cc.incrementAndGet();
countDownLatch.countDown(); countDownLatch.countDown();
} }
@Override @Override
public void onException(Throwable e) { public void onException(Throwable e) {
countDownLatch.countDown();
} }
}); });
countDownLatch.await(3000L, TimeUnit.MILLISECONDS); countDownLatch.await(3000L, TimeUnit.MILLISECONDS);
assertThat(cc.get()).isEqualTo(1);
} }
@Test @Test
......
...@@ -41,5 +41,9 @@ ...@@ -41,5 +41,9 @@
<groupId>org.apache.commons</groupId> <groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId> <artifactId>commons-lang3</artifactId>
</dependency> </dependency>
<dependency>
<groupId>commons-validator</groupId>
<artifactId>commons-validator</artifactId>
</dependency>
</dependencies> </dependencies>
</project> </project>
/*
* 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.common;
import java.util.List;
public class AclConfig {
private List<String> globalWhiteAddrs;
private List<PlainAccessConfig> plainAccessConfigs;
public List<String> getGlobalWhiteAddrs() {
return globalWhiteAddrs;
}
public void setGlobalWhiteAddrs(List<String> globalWhiteAddrs) {
this.globalWhiteAddrs = globalWhiteAddrs;
}
public List<PlainAccessConfig> getPlainAccessConfigs() {
return plainAccessConfigs;
}
public void setPlainAccessConfigs(List<PlainAccessConfig> plainAccessConfigs) {
this.plainAccessConfigs = plainAccessConfigs;
}
}
...@@ -125,8 +125,10 @@ public class MixAll { ...@@ -125,8 +125,10 @@ public class MixAll {
public static String brokerVIPChannel(final boolean isChange, final String brokerAddr) { public static String brokerVIPChannel(final boolean isChange, final String brokerAddr) {
if (isChange) { if (isChange) {
String[] ipAndPort = brokerAddr.split(":"); int split = brokerAddr.lastIndexOf(":");
String brokerAddrNew = ipAndPort[0] + ":" + (Integer.parseInt(ipAndPort[1]) - 2); String ip = brokerAddr.substring(0, split);
String port = brokerAddr.substring(split + 1);
String brokerAddrNew = ip + ":" + (Integer.parseInt(port) - 2);
return brokerAddrNew; return brokerAddrNew;
} else { } else {
return brokerAddr; return brokerAddr;
......
...@@ -23,6 +23,7 @@ import java.io.IOException; ...@@ -23,6 +23,7 @@ import java.io.IOException;
import java.lang.management.ManagementFactory; import java.lang.management.ManagementFactory;
import java.lang.management.RuntimeMXBean; import java.lang.management.RuntimeMXBean;
import java.net.Inet4Address; import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.InetAddress; import java.net.InetAddress;
import java.net.NetworkInterface; import java.net.NetworkInterface;
import java.text.NumberFormat; import java.text.NumberFormat;
...@@ -39,6 +40,7 @@ import java.util.zip.CRC32; ...@@ -39,6 +40,7 @@ import java.util.zip.CRC32;
import java.util.zip.DeflaterOutputStream; import java.util.zip.DeflaterOutputStream;
import java.util.zip.InflaterInputStream; import java.util.zip.InflaterInputStream;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.apache.commons.validator.routines.InetAddressValidator;
import org.apache.rocketmq.common.constant.LoggerName; import org.apache.rocketmq.common.constant.LoggerName;
import org.apache.rocketmq.logging.InternalLogger; import org.apache.rocketmq.logging.InternalLogger;
import org.apache.rocketmq.logging.InternalLoggerFactory; import org.apache.rocketmq.logging.InternalLoggerFactory;
...@@ -438,6 +440,18 @@ public class UtilAll { ...@@ -438,6 +440,18 @@ public class UtilAll {
return false; return false;
} }
public static boolean isInternalV6IP(byte[] ip) {
if (ip.length != 16) {
throw new RuntimeException("illegal ipv6 bytes");
}
//FEC0:0000:0000:0000:0000:0000:0000:0000/10
if (ip[0] == (byte) 254 && ip[1] >= (byte) 192) {
return true;
}
return false;
}
private static boolean ipCheck(byte[] ip) { private static boolean ipCheck(byte[] ip) {
if (ip.length != 4) { if (ip.length != 4) {
throw new RuntimeException("illegal ipv4 bytes"); throw new RuntimeException("illegal ipv4 bytes");
...@@ -474,6 +488,15 @@ public class UtilAll { ...@@ -474,6 +488,15 @@ public class UtilAll {
return false; return false;
} }
private static boolean ipV6Check(byte[] ip) {
if (ip.length != 16) {
throw new RuntimeException("illegal ipv6 bytes");
}
InetAddressValidator validator = InetAddressValidator.getInstance();
return validator.isValidInet6Address(ipToIPv6Str(ip));
}
public static String ipToIPv4Str(byte[] ip) { public static String ipToIPv4Str(byte[] ip) {
if (ip.length != 4) { if (ip.length != 4) {
return null; return null;
...@@ -483,6 +506,25 @@ public class UtilAll { ...@@ -483,6 +506,25 @@ public class UtilAll {
.append(".").append(ip[3] & 0xFF).toString(); .append(".").append(ip[3] & 0xFF).toString();
} }
public static String ipToIPv6Str(byte[] ip) {
if (ip.length != 16) {
return null;
}
StringBuilder sb = new StringBuilder();
for (int i = 0; i < ip.length; i++) {
String hex = Integer.toHexString(ip[i] & 0xFF);
if (hex.length() < 2) {
sb.append(0);
}
sb.append(hex);
if (i % 2 == 1 && i < ip.length - 1) {
sb.append(":");
}
}
return sb.toString();
}
public static byte[] getIP() { public static byte[] getIP() {
try { try {
Enumeration allNetInterfaces = NetworkInterface.getNetworkInterfaces(); Enumeration allNetInterfaces = NetworkInterface.getNetworkInterfaces();
...@@ -504,6 +546,17 @@ public class UtilAll { ...@@ -504,6 +546,17 @@ public class UtilAll {
} }
} }
} }
} else if (ip != null && ip instanceof Inet6Address) {
byte[] ipByte = ip.getAddress();
if (ipByte.length == 16) {
if (ipV6Check(ipByte)) {
if (!isInternalV6IP(ipByte)) {
return ipByte;
} else if (internalIP == null) {
internalIP = ipByte;
}
}
}
} }
} }
} }
...@@ -532,12 +585,12 @@ public class UtilAll { ...@@ -532,12 +585,12 @@ public class UtilAll {
} }
} }
public static String List2String(List<String> list,String splitor) { public static String List2String(List<String> list, String splitor) {
if (list == null || list.size() == 0) { if (list == null || list.size() == 0) {
return null; return null;
} }
StringBuffer str = new StringBuffer(); StringBuffer str = new StringBuffer();
for (int i = 0;i < list.size();i++) { for (int i = 0; i < list.size(); i++) {
str.append(list.get(i)); str.append(list.get(i));
if (i == list.size() - 1) { if (i == list.size() - 1) {
continue; continue;
...@@ -547,7 +600,7 @@ public class UtilAll { ...@@ -547,7 +600,7 @@ public class UtilAll {
return str.toString(); return str.toString();
} }
public static List<String> String2List(String str,String splitor) { public static List<String> String2List(String str, String splitor) {
if (StringUtils.isEmpty(str)) { if (StringUtils.isEmpty(str)) {
return null; return null;
} }
......
...@@ -31,17 +31,19 @@ public class MessageClientIDSetter { ...@@ -31,17 +31,19 @@ public class MessageClientIDSetter {
private static long nextStartTime; private static long nextStartTime;
static { static {
LEN = 4 + 2 + 4 + 4 + 2; byte[] ip;
ByteBuffer tempBuffer = ByteBuffer.allocate(10);
tempBuffer.position(2);
tempBuffer.putInt(UtilAll.getPid());
tempBuffer.position(0);
try { try {
tempBuffer.put(UtilAll.getIP()); ip = UtilAll.getIP();
} catch (Exception e) { } catch (Exception e) {
tempBuffer.put(createFakeIP()); ip = createFakeIP();
} }
tempBuffer.position(6); LEN = ip.length + 2 + 4 + 4 + 2;
ByteBuffer tempBuffer = ByteBuffer.allocate(ip.length + 2 + 4);
tempBuffer.position(0);
tempBuffer.put(ip);
tempBuffer.position(ip.length);
tempBuffer.putInt(UtilAll.getPid());
tempBuffer.position(ip.length + 2);
tempBuffer.putInt(MessageClientIDSetter.class.getClassLoader().hashCode()); tempBuffer.putInt(MessageClientIDSetter.class.getClassLoader().hashCode());
FIX_STRING = UtilAll.bytes2string(tempBuffer.array()); FIX_STRING = UtilAll.bytes2string(tempBuffer.array());
setStartTime(System.currentTimeMillis()); setStartTime(System.currentTimeMillis());
...@@ -64,11 +66,12 @@ public class MessageClientIDSetter { ...@@ -64,11 +66,12 @@ public class MessageClientIDSetter {
public static Date getNearlyTimeFromID(String msgID) { public static Date getNearlyTimeFromID(String msgID) {
ByteBuffer buf = ByteBuffer.allocate(8); ByteBuffer buf = ByteBuffer.allocate(8);
byte[] bytes = UtilAll.string2bytes(msgID); byte[] bytes = UtilAll.string2bytes(msgID);
int ipLength = bytes.length == 28 ? 16 : 4;
buf.put((byte) 0); buf.put((byte) 0);
buf.put((byte) 0); buf.put((byte) 0);
buf.put((byte) 0); buf.put((byte) 0);
buf.put((byte) 0); buf.put((byte) 0);
buf.put(bytes, 10, 4); buf.put(bytes, ipLength + 2 + 4, 4);
buf.position(0); buf.position(0);
long spanMS = buf.getLong(); long spanMS = buf.getLong();
Calendar cal = Calendar.getInstance(); Calendar cal = Calendar.getInstance();
...@@ -89,13 +92,18 @@ public class MessageClientIDSetter { ...@@ -89,13 +92,18 @@ public class MessageClientIDSetter {
public static String getIPStrFromID(String msgID) { public static String getIPStrFromID(String msgID) {
byte[] ipBytes = getIPFromID(msgID); byte[] ipBytes = getIPFromID(msgID);
return UtilAll.ipToIPv4Str(ipBytes); if (ipBytes.length == 16) {
return UtilAll.ipToIPv6Str(ipBytes);
} else {
return UtilAll.ipToIPv4Str(ipBytes);
}
} }
public static byte[] getIPFromID(String msgID) { public static byte[] getIPFromID(String msgID) {
byte[] result = new byte[4];
byte[] bytes = UtilAll.string2bytes(msgID); byte[] bytes = UtilAll.string2bytes(msgID);
System.arraycopy(bytes, 0, result, 0, 4); int ipLength = bytes.length == 28 ? 16 : 4;
byte[] result = new byte[ipLength];
System.arraycopy(bytes, 0, result, 0, ipLength);
return result; return result;
} }
......
...@@ -16,9 +16,7 @@ ...@@ -16,9 +16,7 @@
*/ */
package org.apache.rocketmq.common.message; package org.apache.rocketmq.common.message;
import org.apache.rocketmq.common.UtilAll; import java.net.Inet4Address;
import org.apache.rocketmq.common.sysflag.MessageSysFlag;
import java.net.InetAddress; import java.net.InetAddress;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.net.SocketAddress; import java.net.SocketAddress;
...@@ -29,37 +27,41 @@ import java.util.ArrayList; ...@@ -29,37 +27,41 @@ import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import org.apache.rocketmq.common.UtilAll;
import org.apache.rocketmq.common.sysflag.MessageSysFlag;
public class MessageDecoder { public class MessageDecoder {
public final static int MSG_ID_LENGTH = 8 + 8; // public final static int MSG_ID_LENGTH = 8 + 8;
public final static Charset CHARSET_UTF8 = Charset.forName("UTF-8"); public final static Charset CHARSET_UTF8 = Charset.forName("UTF-8");
public final static int MESSAGE_MAGIC_CODE_POSTION = 4; public final static int MESSAGE_MAGIC_CODE_POSTION = 4;
public final static int MESSAGE_FLAG_POSTION = 16; public final static int MESSAGE_FLAG_POSTION = 16;
public final static int MESSAGE_PHYSIC_OFFSET_POSTION = 28; public final static int MESSAGE_PHYSIC_OFFSET_POSTION = 28;
public final static int MESSAGE_STORE_TIMESTAMP_POSTION = 56; // public final static int MESSAGE_STORE_TIMESTAMP_POSTION = 56;
public final static int MESSAGE_MAGIC_CODE = -626843481; public final static int MESSAGE_MAGIC_CODE = -626843481;
public static final char NAME_VALUE_SEPARATOR = 1; public static final char NAME_VALUE_SEPARATOR = 1;
public static final char PROPERTY_SEPARATOR = 2; public static final char PROPERTY_SEPARATOR = 2;
public static final int PHY_POS_POSITION = 4 + 4 + 4 + 4 + 4 + 8; public static final int PHY_POS_POSITION = 4 + 4 + 4 + 4 + 4 + 8;
public static final int BODY_SIZE_POSITION = 4 // 1 TOTALSIZE public static final int SYSFLAG_POSITION = 4 + 4 + 4 + 4 + 4 + 8 + 8;
+ 4 // 2 MAGICCODE // public static final int BODY_SIZE_POSITION = 4 // 1 TOTALSIZE
+ 4 // 3 BODYCRC // + 4 // 2 MAGICCODE
+ 4 // 4 QUEUEID // + 4 // 3 BODYCRC
+ 4 // 5 FLAG // + 4 // 4 QUEUEID
+ 8 // 6 QUEUEOFFSET // + 4 // 5 FLAG
+ 8 // 7 PHYSICALOFFSET // + 8 // 6 QUEUEOFFSET
+ 4 // 8 SYSFLAG // + 8 // 7 PHYSICALOFFSET
+ 8 // 9 BORNTIMESTAMP // + 4 // 8 SYSFLAG
+ 8 // 10 BORNHOST // + 8 // 9 BORNTIMESTAMP
+ 8 // 11 STORETIMESTAMP // + 8 // 10 BORNHOST
+ 8 // 12 STOREHOSTADDRESS // + 8 // 11 STORETIMESTAMP
+ 4 // 13 RECONSUMETIMES // + 8 // 12 STOREHOSTADDRESS
+ 8; // 14 Prepared Transaction Offset // + 4 // 13 RECONSUMETIMES
// + 8; // 14 Prepared Transaction Offset
public static String createMessageId(final ByteBuffer input, final ByteBuffer addr, final long offset) { public static String createMessageId(final ByteBuffer input, final ByteBuffer addr, final long offset) {
input.flip(); input.flip();
input.limit(MessageDecoder.MSG_ID_LENGTH); int msgIDLength = addr.limit() == 8 ? 16 : 28;
input.limit(msgIDLength);
input.put(addr); input.put(addr);
input.putLong(offset); input.putLong(offset);
...@@ -68,8 +70,9 @@ public class MessageDecoder { ...@@ -68,8 +70,9 @@ public class MessageDecoder {
} }
public static String createMessageId(SocketAddress socketAddress, long transactionIdhashCode) { public static String createMessageId(SocketAddress socketAddress, long transactionIdhashCode) {
ByteBuffer byteBuffer = ByteBuffer.allocate(MessageDecoder.MSG_ID_LENGTH);
InetSocketAddress inetSocketAddress = (InetSocketAddress) socketAddress; InetSocketAddress inetSocketAddress = (InetSocketAddress) socketAddress;
int msgIDLength = inetSocketAddress.getAddress() instanceof Inet4Address ? 16 : 28;
ByteBuffer byteBuffer = ByteBuffer.allocate(msgIDLength);
byteBuffer.put(inetSocketAddress.getAddress().getAddress()); byteBuffer.put(inetSocketAddress.getAddress().getAddress());
byteBuffer.putInt(inetSocketAddress.getPort()); byteBuffer.putInt(inetSocketAddress.getPort());
byteBuffer.putLong(transactionIdhashCode); byteBuffer.putLong(transactionIdhashCode);
...@@ -80,15 +83,16 @@ public class MessageDecoder { ...@@ -80,15 +83,16 @@ public class MessageDecoder {
public static MessageId decodeMessageId(final String msgId) throws UnknownHostException { public static MessageId decodeMessageId(final String msgId) throws UnknownHostException {
SocketAddress address; SocketAddress address;
long offset; long offset;
int ipLength = msgId.length() == 32 ? 4 * 2 : 16 * 2;
byte[] ip = UtilAll.string2bytes(msgId.substring(0, 8)); byte[] ip = UtilAll.string2bytes(msgId.substring(0, ipLength));
byte[] port = UtilAll.string2bytes(msgId.substring(8, 16)); byte[] port = UtilAll.string2bytes(msgId.substring(ipLength, ipLength + 8));
ByteBuffer bb = ByteBuffer.wrap(port); ByteBuffer bb = ByteBuffer.wrap(port);
int portInt = bb.getInt(0); int portInt = bb.getInt(0);
address = new InetSocketAddress(InetAddress.getByAddress(ip), portInt); address = new InetSocketAddress(InetAddress.getByAddress(ip), portInt);
// offset // offset
byte[] data = UtilAll.string2bytes(msgId.substring(16, 32)); byte[] data = UtilAll.string2bytes(msgId.substring(ipLength + 8, ipLength + 8 + 16));
bb = ByteBuffer.wrap(data); bb = ByteBuffer.wrap(data);
offset = bb.getLong(0); offset = bb.getLong(0);
...@@ -101,7 +105,24 @@ public class MessageDecoder { ...@@ -101,7 +105,24 @@ public class MessageDecoder {
* @param byteBuffer msg commit log buffer. * @param byteBuffer msg commit log buffer.
*/ */
public static Map<String, String> decodeProperties(java.nio.ByteBuffer byteBuffer) { public static Map<String, String> decodeProperties(java.nio.ByteBuffer byteBuffer) {
int topicLengthPosition = BODY_SIZE_POSITION + 4 + byteBuffer.getInt(BODY_SIZE_POSITION); int sysFlag = byteBuffer.getInt(SYSFLAG_POSITION);
int bornhostLength = (sysFlag & MessageSysFlag.BORNHOST_V6_FLAG) == 0 ? 8 : 20;
int storehostAddressLength = (sysFlag & MessageSysFlag.STOREHOSTADDRESS_V6_FLAG) == 0 ? 8 : 20;
int bodySizePosition = 4 // 1 TOTALSIZE
+ 4 // 2 MAGICCODE
+ 4 // 3 BODYCRC
+ 4 // 4 QUEUEID
+ 4 // 5 FLAG
+ 8 // 6 QUEUEOFFSET
+ 8 // 7 PHYSICALOFFSET
+ 4 // 8 SYSFLAG
+ 8 // 9 BORNTIMESTAMP
+ bornhostLength // 10 BORNHOST
+ 8 // 11 STORETIMESTAMP
+ storehostAddressLength // 12 STOREHOSTADDRESS
+ 4 // 13 RECONSUMETIMES
+ 8; // 14 Prepared Transaction Offset
int topicLengthPosition = bodySizePosition + 4 + byteBuffer.getInt(bodySizePosition);
byte topicLength = byteBuffer.get(topicLengthPosition); byte topicLength = byteBuffer.get(topicLengthPosition);
...@@ -139,6 +160,8 @@ public class MessageDecoder { ...@@ -139,6 +160,8 @@ public class MessageDecoder {
byte[] propertiesBytes = properties.getBytes(CHARSET_UTF8); byte[] propertiesBytes = properties.getBytes(CHARSET_UTF8);
short propertiesLength = (short) propertiesBytes.length; short propertiesLength = (short) propertiesBytes.length;
int sysFlag = messageExt.getSysFlag(); int sysFlag = messageExt.getSysFlag();
int bornhostLength = (sysFlag & MessageSysFlag.BORNHOST_V6_FLAG) == 0 ? 8 : 20;
int storehostAddressLength = (sysFlag & MessageSysFlag.STOREHOSTADDRESS_V6_FLAG) == 0 ? 8 : 20;
byte[] newBody = messageExt.getBody(); byte[] newBody = messageExt.getBody();
if (needCompress && (sysFlag & MessageSysFlag.COMPRESSED_FLAG) == MessageSysFlag.COMPRESSED_FLAG) { if (needCompress && (sysFlag & MessageSysFlag.COMPRESSED_FLAG) == MessageSysFlag.COMPRESSED_FLAG) {
newBody = UtilAll.compress(body, 5); newBody = UtilAll.compress(body, 5);
...@@ -158,9 +181,9 @@ public class MessageDecoder { ...@@ -158,9 +181,9 @@ public class MessageDecoder {
+ 8 // 7 PHYSICALOFFSET + 8 // 7 PHYSICALOFFSET
+ 4 // 8 SYSFLAG + 4 // 8 SYSFLAG
+ 8 // 9 BORNTIMESTAMP + 8 // 9 BORNTIMESTAMP
+ 8 // 10 BORNHOST + bornhostLength // 10 BORNHOST
+ 8 // 11 STORETIMESTAMP + 8 // 11 STORETIMESTAMP
+ 8 // 12 STOREHOSTADDRESS + storehostAddressLength // 12 STOREHOSTADDRESS
+ 4 // 13 RECONSUMETIMES + 4 // 13 RECONSUMETIMES
+ 8 // 14 Prepared Transaction Offset + 8 // 14 Prepared Transaction Offset
+ 4 + bodyLength // 14 BODY + 4 + bodyLength // 14 BODY
...@@ -291,8 +314,9 @@ public class MessageDecoder { ...@@ -291,8 +314,9 @@ public class MessageDecoder {
msgExt.setBornTimestamp(bornTimeStamp); msgExt.setBornTimestamp(bornTimeStamp);
// 10 BORNHOST // 10 BORNHOST
byte[] bornHost = new byte[4]; int bornhostIPLength = (sysFlag & MessageSysFlag.BORNHOST_V6_FLAG) == 0 ? 4 : 16;
byteBuffer.get(bornHost, 0, 4); byte[] bornHost = new byte[bornhostIPLength];
byteBuffer.get(bornHost, 0, bornhostIPLength);
int port = byteBuffer.getInt(); int port = byteBuffer.getInt();
msgExt.setBornHost(new InetSocketAddress(InetAddress.getByAddress(bornHost), port)); msgExt.setBornHost(new InetSocketAddress(InetAddress.getByAddress(bornHost), port));
...@@ -301,8 +325,9 @@ public class MessageDecoder { ...@@ -301,8 +325,9 @@ public class MessageDecoder {
msgExt.setStoreTimestamp(storeTimestamp); msgExt.setStoreTimestamp(storeTimestamp);
// 12 STOREHOST // 12 STOREHOST
byte[] storeHost = new byte[4]; int storehostIPLength = (sysFlag & MessageSysFlag.STOREHOSTADDRESS_V6_FLAG) == 0 ? 4 : 16;
byteBuffer.get(storeHost, 0, 4); byte[] storeHost = new byte[storehostIPLength];
byteBuffer.get(storeHost, 0, storehostIPLength);
port = byteBuffer.getInt(); port = byteBuffer.getInt();
msgExt.setStoreHost(new InetSocketAddress(InetAddress.getByAddress(storeHost), port)); msgExt.setStoreHost(new InetSocketAddress(InetAddress.getByAddress(storeHost), port));
...@@ -348,7 +373,8 @@ public class MessageDecoder { ...@@ -348,7 +373,8 @@ public class MessageDecoder {
msgExt.setProperties(map); msgExt.setProperties(map);
} }
ByteBuffer byteBufferMsgId = ByteBuffer.allocate(MSG_ID_LENGTH); int msgIDLength = storehostIPLength + 4 + 8;
ByteBuffer byteBufferMsgId = ByteBuffer.allocate(msgIDLength);
String msgId = createMessageId(byteBufferMsgId, msgExt.getStoreHostBytes(), msgExt.getCommitLogOffset()); String msgId = createMessageId(byteBufferMsgId, msgExt.getStoreHostBytes(), msgExt.getCommitLogOffset());
msgExt.setMsgId(msgId); msgExt.setMsgId(msgId);
......
...@@ -16,6 +16,8 @@ ...@@ -16,6 +16,8 @@
*/ */
package org.apache.rocketmq.common.message; package org.apache.rocketmq.common.message;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.net.SocketAddress; import java.net.SocketAddress;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
...@@ -66,14 +68,26 @@ public class MessageExt extends Message { ...@@ -66,14 +68,26 @@ public class MessageExt extends Message {
public static ByteBuffer socketAddress2ByteBuffer(final SocketAddress socketAddress, final ByteBuffer byteBuffer) { public static ByteBuffer socketAddress2ByteBuffer(final SocketAddress socketAddress, final ByteBuffer byteBuffer) {
InetSocketAddress inetSocketAddress = (InetSocketAddress) socketAddress; InetSocketAddress inetSocketAddress = (InetSocketAddress) socketAddress;
byteBuffer.put(inetSocketAddress.getAddress().getAddress(), 0, 4); InetAddress address = inetSocketAddress.getAddress();
if (address instanceof Inet4Address) {
byteBuffer.put(inetSocketAddress.getAddress().getAddress(), 0, 4);
} else {
byteBuffer.put(inetSocketAddress.getAddress().getAddress(), 0, 16);
}
byteBuffer.putInt(inetSocketAddress.getPort()); byteBuffer.putInt(inetSocketAddress.getPort());
byteBuffer.flip(); byteBuffer.flip();
return byteBuffer; return byteBuffer;
} }
public static ByteBuffer socketAddress2ByteBuffer(SocketAddress socketAddress) { public static ByteBuffer socketAddress2ByteBuffer(SocketAddress socketAddress) {
ByteBuffer byteBuffer = ByteBuffer.allocate(8); InetSocketAddress inetSocketAddress = (InetSocketAddress) socketAddress;
InetAddress address = inetSocketAddress.getAddress();
ByteBuffer byteBuffer;
if (address instanceof Inet4Address) {
byteBuffer = ByteBuffer.allocate(4 + 4);
} else {
byteBuffer = ByteBuffer.allocate(16 + 4);
}
return socketAddress2ByteBuffer(socketAddress, byteBuffer); return socketAddress2ByteBuffer(socketAddress, byteBuffer);
} }
...@@ -167,6 +181,10 @@ public class MessageExt extends Message { ...@@ -167,6 +181,10 @@ public class MessageExt extends Message {
this.sysFlag = sysFlag; this.sysFlag = sysFlag;
} }
public void setStoreHostAddressV6Flag() { this.sysFlag = this.sysFlag | MessageSysFlag.STOREHOSTADDRESS_V6_FLAG; }
public void setBornHostV6Flag() { this.sysFlag = this.sysFlag | MessageSysFlag.BORNHOST_V6_FLAG; }
public int getBodyCRC() { public int getBodyCRC() {
return bodyCRC; return bodyCRC;
} }
......
...@@ -78,6 +78,8 @@ public class RequestCode { ...@@ -78,6 +78,8 @@ public class RequestCode {
public static final int UPDATE_GLOBAL_WHITE_ADDRS_CONFIG = 53; public static final int UPDATE_GLOBAL_WHITE_ADDRS_CONFIG = 53;
public static final int GET_BROKER_CLUSTER_ACL_CONFIG = 54;
public static final int PUT_KV_CONFIG = 100; public static final int PUT_KV_CONFIG = 100;
public static final int GET_KV_CONFIG = 101; public static final int GET_KV_CONFIG = 101;
......
/*
* 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.common.protocol.header;
import org.apache.rocketmq.common.PlainAccessConfig;
import org.apache.rocketmq.remoting.protocol.RemotingSerializable;
import java.util.List;
public class GetBrokerClusterAclConfigResponseBody extends RemotingSerializable {
private List<String> globalWhiteAddrs;
private List<PlainAccessConfig> plainAccessConfigs;
public List<String> getGlobalWhiteAddrs() {
return globalWhiteAddrs;
}
public void setGlobalWhiteAddrs(List<String> globalWhiteAddrs) {
this.globalWhiteAddrs = globalWhiteAddrs;
}
public List<PlainAccessConfig> getPlainAccessConfigs() {
return plainAccessConfigs;
}
public void setPlainAccessConfigs(List<PlainAccessConfig> plainAccessConfigs) {
this.plainAccessConfigs = plainAccessConfigs;
}
}
/*
* 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.common.protocol.header;
import org.apache.rocketmq.common.PlainAccessConfig;
import org.apache.rocketmq.remoting.CommandCustomHeader;
import org.apache.rocketmq.remoting.annotation.CFNotNull;
import org.apache.rocketmq.remoting.exception.RemotingCommandException;
import java.util.List;
public class GetBrokerClusterAclConfigResponseHeader implements CommandCustomHeader {
@CFNotNull
private List<PlainAccessConfig> plainAccessConfigs;
@Override
public void checkFields() throws RemotingCommandException {
}
public List<PlainAccessConfig> getPlainAccessConfigs() {
return plainAccessConfigs;
}
public void setPlainAccessConfigs(List<PlainAccessConfig> plainAccessConfigs) {
this.plainAccessConfigs = plainAccessConfigs;
}
}
...@@ -23,6 +23,8 @@ public class MessageSysFlag { ...@@ -23,6 +23,8 @@ public class MessageSysFlag {
public final static int TRANSACTION_PREPARED_TYPE = 0x1 << 2; public final static int TRANSACTION_PREPARED_TYPE = 0x1 << 2;
public final static int TRANSACTION_COMMIT_TYPE = 0x2 << 2; public final static int TRANSACTION_COMMIT_TYPE = 0x2 << 2;
public final static int TRANSACTION_ROLLBACK_TYPE = 0x3 << 2; public final static int TRANSACTION_ROLLBACK_TYPE = 0x3 << 2;
public final static int BORNHOST_V6_FLAG = 0x1 << 4;
public final static int STOREHOSTADDRESS_V6_FLAG = 0x1 << 5;
public static int getTransactionValue(final int flag) { public static int getTransactionValue(final int flag) {
return flag & TRANSACTION_ROLLBACK_TYPE; return flag & TRANSACTION_ROLLBACK_TYPE;
...@@ -35,4 +37,5 @@ public class MessageSysFlag { ...@@ -35,4 +37,5 @@ public class MessageSysFlag {
public static int clearCompressedFlag(final int flag) { public static int clearCompressedFlag(final int flag) {
return flag & (~COMPRESSED_FLAG); return flag & (~COMPRESSED_FLAG);
} }
} }
...@@ -98,6 +98,15 @@ public class UtilAllTest { ...@@ -98,6 +98,15 @@ public class UtilAllTest {
assertThat(UtilAll.isBlank("Hello")).isFalse(); assertThat(UtilAll.isBlank("Hello")).isFalse();
} }
@Test
public void testIPv6Check() {
byte[] nonInternalIp = UtilAll.string2bytes("24084004018081003FAA1DDE2B3F898A");
byte[] internalIp = UtilAll.string2bytes("FEC0000000000000000000000000FFFF");
assertThat(UtilAll.isInternalV6IP(nonInternalIp)).isFalse();
assertThat(UtilAll.isInternalV6IP(internalIp)).isTrue();
assertThat(UtilAll.ipToIPv6Str(nonInternalIp).toUpperCase()).isEqualTo("2408:4004:0180:8100:3FAA:1DDE:2B3F:898A");
}
static class DemoConfig { static class DemoConfig {
private int demoWidth = 0; private int demoWidth = 0;
private int demoLength = 0; private int demoLength = 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.common.message;
import java.util.Calendar;
import java.util.Date;
import org.junit.Test;
import static org.assertj.core.api.Assertions.assertThat;
public class MessageClientIDSetterTest {
@Test
public void testGetIPStrFromID() {
String ipv4HostMsgId = "C0A803CA00002A9F0000000000031367";
String ipv6HostMsgId = "24084004018081003FAA1DDE2B3F898A00002A9F0000000000000CA0";
String v4Ip = "192.168.3.202";
String v6Ip = "2408:4004:0180:8100:3faa:1dde:2b3f:898a";
assertThat(MessageClientIDSetter.getIPStrFromID(ipv4HostMsgId)).isEqualTo(v4Ip);
assertThat(MessageClientIDSetter.getIPStrFromID(ipv6HostMsgId)).isEqualTo(v6Ip);
}
}
...@@ -25,6 +25,7 @@ import java.net.UnknownHostException; ...@@ -25,6 +25,7 @@ import java.net.UnknownHostException;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.util.Map; import java.util.Map;
import static org.apache.rocketmq.common.message.MessageDecoder.createMessageId;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
public class MessageDecoderTest { public class MessageDecoderTest {
...@@ -77,4 +78,172 @@ public class MessageDecoderTest { ...@@ -77,4 +78,172 @@ public class MessageDecoderTest {
assertThat("hello").isEqualTo(properties.get("b")); assertThat("hello").isEqualTo(properties.get("b"));
assertThat("3.14").isEqualTo(properties.get("c")); assertThat("3.14").isEqualTo(properties.get("c"));
} }
@Test
public void testDecodePropertiesOnIPv6Host() {
MessageExt messageExt = new MessageExt();
messageExt.setMsgId("24084004018081003FAA1DDE2B3F898A00002A9F0000000000000CA0");
messageExt.setBornHostV6Flag();
messageExt.setStoreHostAddressV6Flag();
messageExt.setTopic("abc");
messageExt.setBody("hello!q!".getBytes());
try {
messageExt.setBornHost(new InetSocketAddress(InetAddress.getByName("1050:0000:0000:0000:0005:0600:300c:326b"), 0));
} catch (UnknownHostException e) {
e.printStackTrace();
assertThat(Boolean.FALSE).isTrue();
}
messageExt.setBornTimestamp(System.currentTimeMillis());
messageExt.setCommitLogOffset(123456);
messageExt.setPreparedTransactionOffset(0);
messageExt.setQueueId(0);
messageExt.setQueueOffset(123);
messageExt.setReconsumeTimes(0);
try {
messageExt.setStoreHost(new InetSocketAddress(InetAddress.getByName("::1"), 0));
} catch (UnknownHostException e) {
e.printStackTrace();
assertThat(Boolean.FALSE).isTrue();
}
messageExt.putUserProperty("a", "123");
messageExt.putUserProperty("b", "hello");
messageExt.putUserProperty("c", "3.14");
byte[] msgBytes = new byte[0];
try {
msgBytes = MessageDecoder.encode(messageExt, false);
} catch (Exception e) {
e.printStackTrace();
assertThat(Boolean.FALSE).isTrue();
}
ByteBuffer byteBuffer = ByteBuffer.allocate(msgBytes.length);
byteBuffer.put(msgBytes);
Map<String, String> properties = MessageDecoder.decodeProperties(byteBuffer);
assertThat(properties).isNotNull();
assertThat("123").isEqualTo(properties.get("a"));
assertThat("hello").isEqualTo(properties.get("b"));
assertThat("3.14").isEqualTo(properties.get("c"));
}
@Test
public void testEncodeAndDecode() {
MessageExt messageExt = new MessageExt();
messageExt.setMsgId("645100FA00002A9F000000489A3AA09E");
messageExt.setTopic("abc");
messageExt.setBody("hello!q!".getBytes());
try {
messageExt.setBornHost(new InetSocketAddress(InetAddress.getByName("127.0.0.1"), 0));
} catch (UnknownHostException e) {
e.printStackTrace();
assertThat(Boolean.FALSE).isTrue();
}
messageExt.setBornTimestamp(System.currentTimeMillis());
messageExt.setCommitLogOffset(123456);
messageExt.setPreparedTransactionOffset(0);
messageExt.setQueueId(1);
messageExt.setQueueOffset(123);
messageExt.setReconsumeTimes(0);
try {
messageExt.setStoreHost(new InetSocketAddress(InetAddress.getLocalHost(), 0));
} catch (UnknownHostException e) {
e.printStackTrace();
assertThat(Boolean.FALSE).isTrue();
}
messageExt.putUserProperty("a", "123");
messageExt.putUserProperty("b", "hello");
messageExt.putUserProperty("c", "3.14");
byte[] msgBytes = new byte[0];
try {
msgBytes = MessageDecoder.encode(messageExt, false);
} catch (Exception e) {
e.printStackTrace();
assertThat(Boolean.FALSE).isTrue();
}
ByteBuffer byteBuffer = ByteBuffer.allocate(msgBytes.length);
byteBuffer.put(msgBytes);
byteBuffer.clear();
MessageExt decodedMsg = MessageDecoder.decode(byteBuffer);
assertThat(decodedMsg).isNotNull();
assertThat(1).isEqualTo(decodedMsg.getQueueId());
assertThat(123456L).isEqualTo(decodedMsg.getCommitLogOffset());
assertThat("hello!q!".getBytes()).isEqualTo(decodedMsg.getBody());
int msgIDLength = 4 + 4 + 8;
ByteBuffer byteBufferMsgId = ByteBuffer.allocate(msgIDLength);
String msgId = createMessageId(byteBufferMsgId, messageExt.getStoreHostBytes(), messageExt.getCommitLogOffset());
assertThat(msgId).isEqualTo(decodedMsg.getMsgId());
assertThat("abc").isEqualTo(decodedMsg.getTopic());
}
@Test
public void testEncodeAndDecodeOnIPv6Host() {
MessageExt messageExt = new MessageExt();
messageExt.setMsgId("24084004018081003FAA1DDE2B3F898A00002A9F0000000000000CA0");
messageExt.setBornHostV6Flag();
messageExt.setStoreHostAddressV6Flag();
messageExt.setTopic("abc");
messageExt.setBody("hello!q!".getBytes());
try {
messageExt.setBornHost(new InetSocketAddress(InetAddress.getByName("1050:0000:0000:0000:0005:0600:300c:326b"), 0));
} catch (UnknownHostException e) {
e.printStackTrace();
assertThat(Boolean.FALSE).isTrue();
}
messageExt.setBornTimestamp(System.currentTimeMillis());
messageExt.setCommitLogOffset(123456);
messageExt.setPreparedTransactionOffset(0);
messageExt.setQueueId(1);
messageExt.setQueueOffset(123);
messageExt.setReconsumeTimes(0);
try {
messageExt.setStoreHost(new InetSocketAddress(InetAddress.getByName("::1"), 0));
} catch (UnknownHostException e) {
e.printStackTrace();
assertThat(Boolean.FALSE).isTrue();
}
messageExt.putUserProperty("a", "123");
messageExt.putUserProperty("b", "hello");
messageExt.putUserProperty("c", "3.14");
byte[] msgBytes = new byte[0];
try {
msgBytes = MessageDecoder.encode(messageExt, false);
} catch (Exception e) {
e.printStackTrace();
assertThat(Boolean.FALSE).isTrue();
}
ByteBuffer byteBuffer = ByteBuffer.allocate(msgBytes.length);
byteBuffer.put(msgBytes);
byteBuffer.clear();
MessageExt decodedMsg = MessageDecoder.decode(byteBuffer);
assertThat(decodedMsg).isNotNull();
assertThat(1).isEqualTo(decodedMsg.getQueueId());
assertThat(123456L).isEqualTo(decodedMsg.getCommitLogOffset());
assertThat("hello!q!".getBytes()).isEqualTo(decodedMsg.getBody());
assertThat(48).isEqualTo(decodedMsg.getSysFlag());
int msgIDLength = 16 + 4 + 8;
ByteBuffer byteBufferMsgId = ByteBuffer.allocate(msgIDLength);
String msgId = createMessageId(byteBufferMsgId, messageExt.getStoreHostBytes(), messageExt.getCommitLogOffset());
assertThat(msgId).isEqualTo(decodedMsg.getMsgId());
assertThat("abc").isEqualTo(decodedMsg.getTopic());
}
} }
...@@ -66,7 +66,11 @@ public class AsyncProducer { ...@@ -66,7 +66,11 @@ public class AsyncProducer {
// 启动Producer实例 // 启动Producer实例
producer.start(); producer.start();
producer.setRetryTimesWhenSendAsyncFailed(0); producer.setRetryTimesWhenSendAsyncFailed(0);
for (int i = 0; i < 100; i++) {
int messageCount = 100;
// 根据消息数量实例化倒计时计算器
final CountDownLatch2 countDownLatch = new CountDownLatch2(messageCount);
for (int i = 0; i < messageCount; i++) {
final int index = i; final int index = i;
// 创建消息,并指定Topic,Tag和消息体 // 创建消息,并指定Topic,Tag和消息体
Message msg = new Message("TopicTest", Message msg = new Message("TopicTest",
...@@ -87,6 +91,8 @@ public class AsyncProducer { ...@@ -87,6 +91,8 @@ public class AsyncProducer {
} }
}); });
} }
// 等待5s
countDownLatch.await(5, TimeUnit.SECONDS);
// 如果不再发送消息,关闭Producer实例。 // 如果不再发送消息,关闭Producer实例。
producer.shutdown(); producer.shutdown();
} }
......
...@@ -152,6 +152,18 @@ sh mqadmin clusterAclConfigVersion -n 192.168.1.2:9876 -c DefaultCluster ...@@ -152,6 +152,18 @@ sh mqadmin clusterAclConfigVersion -n 192.168.1.2:9876 -c DefaultCluster
| c | eg:DefaultCluster | 指定集群名称(与broker地址二选一) | | c | eg:DefaultCluster | 指定集群名称(与broker地址二选一) |
| b | eg:192.168.12.134:10911 | 指定broker地址(与集群名称二选一) | | b | eg:192.168.12.134:10911 | 指定broker地址(与集群名称二选一) |
### 7.5 查询集群/Broker的ACL配置文件全部内容
该命令的示例如下:
sh mqadmin getAccessConfigSubCommand -n 192.168.1.2:9876 -c DefaultCluster
说明:如果指定的是集群名称,则会在集群中各个broker节点执行该命令;否则会在单个broker节点执行该命令。
| 参数 | 取值 | 含义 |
| --- | --- | --- |
| n | eg:192.168.1.2:9876 | namesrv地址(必填) |
| c | eg:DefaultCluster | 指定集群名称(与broker地址二选一) |
| b | eg:192.168.12.134:10911 | 指定broker地址(与集群名称二选一) |
**特别注意**开启Acl鉴权认证后导致Master/Slave和Dledger模式下Broker同步数据异常的问题, **特别注意**开启Acl鉴权认证后导致Master/Slave和Dledger模式下Broker同步数据异常的问题,
在社区[4.5.1]版本中已经修复,具体的PR链接为:https://github.com/apache/rocketmq/pull/1149; 在社区[4.5.1]版本中已经修复,具体的PR链接为:https://github.com/apache/rocketmq/pull/1149;
\ No newline at end of file
...@@ -32,7 +32,7 @@ ...@@ -32,7 +32,7 @@
(2) 异步刷盘:能够充分利用OS的PageCache的优势,只要消息写入PageCache即可将成功的ACK返回给Producer端。消息刷盘采用后台异步线程提交的方式进行,降低了读写延迟,提高了MQ的性能和吞吐量。 (2) 异步刷盘:能够充分利用OS的PageCache的优势,只要消息写入PageCache即可将成功的ACK返回给Producer端。消息刷盘采用后台异步线程提交的方式进行,降低了读写延迟,提高了MQ的性能和吞吐量。
### 2 通信机制 ### 2 通信机制
RocketMQ消息队列集群主要包括NameServe、Broker(Master/Slave)、Producer、Consumer4个角色,基本通讯流程如下: RocketMQ消息队列集群主要包括NameServer、Broker(Master/Slave)、Producer、Consumer4个角色,基本通讯流程如下:
(1) Broker启动后需要完成一次将自己注册至NameServer的操作;随后每隔30s时间定时向NameServer上报Topic路由信息。 (1) Broker启动后需要完成一次将自己注册至NameServer的操作;随后每隔30s时间定时向NameServer上报Topic路由信息。
...@@ -57,7 +57,7 @@ Header字段 | 类型 | Request说明 | Response说明 ...@@ -57,7 +57,7 @@ Header字段 | 类型 | Request说明 | Response说明
code |int | 请求操作码,应答方根据不同的请求码进行不同的业务处理 | 应答响应码。0表示成功,非0则表示各种错误 code |int | 请求操作码,应答方根据不同的请求码进行不同的业务处理 | 应答响应码。0表示成功,非0则表示各种错误
language | LanguageCode | 请求方实现的语言 | 应答方实现的语言 language | LanguageCode | 请求方实现的语言 | 应答方实现的语言
version | int | 请求方程序的版本 | 应答方程序的版本 version | int | 请求方程序的版本 | 应答方程序的版本
opaque | int |相当于reqeustId,在同一个连接上的不同请求标识码,与响应消息中的相对应 | 应答不做修改直接返回 opaque | int |相当于requestId,在同一个连接上的不同请求标识码,与响应消息中的相对应 | 应答不做修改直接返回
flag | int | 区分是普通RPC还是onewayRPC得标志 | 区分是普通RPC还是onewayRPC得标志 flag | int | 区分是普通RPC还是onewayRPC得标志 | 区分是普通RPC还是onewayRPC得标志
remark | String | 传输自定义文本信息 | 传输自定义文本信息 remark | String | 传输自定义文本信息 | 传输自定义文本信息
extFields | HashMap<String, String> | 请求自定义扩展信息 | 响应自定义扩展信息 extFields | HashMap<String, String> | 请求自定义扩展信息 | 响应自定义扩展信息
...@@ -95,7 +95,7 @@ M1 | NettyServerCodecThread_%d | Worker线程池 ...@@ -95,7 +95,7 @@ M1 | NettyServerCodecThread_%d | Worker线程池
M2 | RemotingExecutorThread_%d | 业务processor处理线程池 M2 | RemotingExecutorThread_%d | 业务processor处理线程池
### 3 消息过滤 ### 3 消息过滤
RocketMQ分布式消息队列的消息过滤方式有别于其它MQ中间件,是在Consumer端订阅消息时再做消息过滤的。RocketMQ这么做是还是在于其Producer端写入消息和Consomer端订阅消息采用分离存储的机制来实现的,Consumer端订阅消息是需要通过ConsumeQueue这个消息消费的逻辑队列拿到一个索引,然后再从CommitLog里面读取真正的消息实体内容,所以说到底也是还绕不开其存储结构。其ConsumeQueue的存储结构如下,可以看到其中有8个字节存储的Message Tag的哈希值,基于Tag的消息过滤正式基于这个字段值的。 RocketMQ分布式消息队列的消息过滤方式有别于其它MQ中间件,是在Consumer端订阅消息时再做消息过滤的。RocketMQ这么做是在于其Producer端写入消息和Consumer端订阅消息采用分离存储的机制来实现的,Consumer端订阅消息是需要通过ConsumeQueue这个消息消费的逻辑队列拿到一个索引,然后再从CommitLog里面读取真正的消息实体内容,所以说到底也是还绕不开其存储结构。其ConsumeQueue的存储结构如下,可以看到其中有8个字节存储的Message Tag的哈希值,基于Tag的消息过滤正式基于这个字段值的。
![](image/rocketmq_design_7.png) ![](image/rocketmq_design_7.png)
......
...@@ -16,7 +16,8 @@ ...@@ -16,7 +16,8 @@
limitations under the License. limitations under the License.
--> -->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<parent> <parent>
<groupId>org.apache</groupId> <groupId>org.apache</groupId>
...@@ -159,7 +160,7 @@ ...@@ -159,7 +160,7 @@
</executions> </executions>
<configuration> <configuration>
<rules> <rules>
<banCircularDependencies /> <banCircularDependencies/>
</rules> </rules>
<fail>true</fail> <fail>true</fail>
</configuration> </configuration>
...@@ -568,7 +569,7 @@ ...@@ -568,7 +569,7 @@
<dependency> <dependency>
<groupId>com.alibaba</groupId> <groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId> <artifactId>fastjson</artifactId>
<version>1.2.51</version> <version>1.2.61</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.javassist</groupId> <groupId>org.javassist</groupId>
...@@ -620,6 +621,13 @@ ...@@ -620,6 +621,13 @@
<artifactId>log4j-slf4j-impl</artifactId> <artifactId>log4j-slf4j-impl</artifactId>
<version>2.7</version> <version>2.7</version>
</dependency> </dependency>
<dependency>
<groupId>commons-validator</groupId>
<artifactId>commons-validator</artifactId>
<version>1.6</version>
</dependency>
</dependencies> </dependencies>
</dependencyManagement> </dependencyManagement>
</project> </project>
...@@ -17,18 +17,17 @@ ...@@ -17,18 +17,17 @@
package org.apache.rocketmq.remoting.common; package org.apache.rocketmq.remoting.common;
import io.netty.channel.Channel; import io.netty.channel.Channel;
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.logging.InternalLogger;
import org.apache.rocketmq.logging.InternalLoggerFactory;
import org.apache.rocketmq.remoting.protocol.RemotingCommand;
import java.io.IOException; import java.io.IOException;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.net.SocketAddress; import java.net.SocketAddress;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel; import java.nio.channels.SocketChannel;
import org.apache.rocketmq.logging.InternalLogger;
import org.apache.rocketmq.logging.InternalLoggerFactory;
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.remoting.protocol.RemotingCommand;
public class RemotingHelper { public class RemotingHelper {
public static final String ROCKETMQ_REMOTING = "RocketmqRemoting"; public static final String ROCKETMQ_REMOTING = "RocketmqRemoting";
...@@ -53,8 +52,10 @@ public class RemotingHelper { ...@@ -53,8 +52,10 @@ public class RemotingHelper {
} }
public static SocketAddress string2SocketAddress(final String addr) { public static SocketAddress string2SocketAddress(final String addr) {
String[] s = addr.split(":"); int split = addr.lastIndexOf(":");
InetSocketAddress isa = new InetSocketAddress(s[0], Integer.parseInt(s[1])); String host = addr.substring(0, split);
String port = addr.substring(split + 1);
InetSocketAddress isa = new InetSocketAddress(host, Integer.parseInt(port));
return isa; return isa;
} }
......
...@@ -31,7 +31,6 @@ import java.nio.channels.SocketChannel; ...@@ -31,7 +31,6 @@ import java.nio.channels.SocketChannel;
import java.nio.channels.spi.SelectorProvider; import java.nio.channels.spi.SelectorProvider;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Enumeration; import java.util.Enumeration;
import org.apache.rocketmq.logging.InternalLogger; import org.apache.rocketmq.logging.InternalLogger;
import org.apache.rocketmq.logging.InternalLoggerFactory; import org.apache.rocketmq.logging.InternalLoggerFactory;
...@@ -145,8 +144,10 @@ public class RemotingUtil { ...@@ -145,8 +144,10 @@ public class RemotingUtil {
} }
public static SocketAddress string2SocketAddress(final String addr) { public static SocketAddress string2SocketAddress(final String addr) {
String[] s = addr.split(":"); int split = addr.lastIndexOf(":");
InetSocketAddress isa = new InetSocketAddress(s[0], Integer.parseInt(s[1])); String host = addr.substring(0, split);
String port = addr.substring(split + 1);
InetSocketAddress isa = new InetSocketAddress(host, Integer.parseInt(port));
return isa; return isa;
} }
......
...@@ -16,6 +16,8 @@ ...@@ -16,6 +16,8 @@
*/ */
package org.apache.rocketmq.store; package org.apache.rocketmq.store;
import java.net.Inet6Address;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
...@@ -26,14 +28,14 @@ import java.util.concurrent.TimeUnit; ...@@ -26,14 +28,14 @@ import java.util.concurrent.TimeUnit;
import org.apache.rocketmq.common.ServiceThread; import org.apache.rocketmq.common.ServiceThread;
import org.apache.rocketmq.common.UtilAll; import org.apache.rocketmq.common.UtilAll;
import org.apache.rocketmq.common.constant.LoggerName; import org.apache.rocketmq.common.constant.LoggerName;
import org.apache.rocketmq.logging.InternalLogger;
import org.apache.rocketmq.logging.InternalLoggerFactory;
import org.apache.rocketmq.common.message.MessageAccessor; import org.apache.rocketmq.common.message.MessageAccessor;
import org.apache.rocketmq.common.message.MessageConst; import org.apache.rocketmq.common.message.MessageConst;
import org.apache.rocketmq.common.message.MessageDecoder; import org.apache.rocketmq.common.message.MessageDecoder;
import org.apache.rocketmq.common.message.MessageExt; import org.apache.rocketmq.common.message.MessageExt;
import org.apache.rocketmq.common.message.MessageExtBatch; import org.apache.rocketmq.common.message.MessageExtBatch;
import org.apache.rocketmq.common.sysflag.MessageSysFlag; import org.apache.rocketmq.common.sysflag.MessageSysFlag;
import org.apache.rocketmq.logging.InternalLogger;
import org.apache.rocketmq.logging.InternalLoggerFactory;
import org.apache.rocketmq.store.config.BrokerRole; import org.apache.rocketmq.store.config.BrokerRole;
import org.apache.rocketmq.store.config.FlushDiskType; import org.apache.rocketmq.store.config.FlushDiskType;
import org.apache.rocketmq.store.ha.HAService; import org.apache.rocketmq.store.ha.HAService;
...@@ -270,11 +272,21 @@ public class CommitLog { ...@@ -270,11 +272,21 @@ public class CommitLog {
long bornTimeStamp = byteBuffer.getLong(); long bornTimeStamp = byteBuffer.getLong();
ByteBuffer byteBuffer1 = byteBuffer.get(bytesContent, 0, 8); ByteBuffer byteBuffer1;
if ((sysFlag & MessageSysFlag.BORNHOST_V6_FLAG) == 0) {
byteBuffer1 = byteBuffer.get(bytesContent, 0, 4 + 4);
} else {
byteBuffer1 = byteBuffer.get(bytesContent, 0, 16 + 4);
}
long storeTimestamp = byteBuffer.getLong(); long storeTimestamp = byteBuffer.getLong();
ByteBuffer byteBuffer2 = byteBuffer.get(bytesContent, 0, 8); ByteBuffer byteBuffer2;
if ((sysFlag & MessageSysFlag.STOREHOSTADDRESS_V6_FLAG) == 0) {
byteBuffer2 = byteBuffer.get(bytesContent, 0, 4 + 4);
} else {
byteBuffer2 = byteBuffer.get(bytesContent, 0, 16 + 4);
}
int reconsumeTimes = byteBuffer.getInt(); int reconsumeTimes = byteBuffer.getInt();
...@@ -339,7 +351,7 @@ public class CommitLog { ...@@ -339,7 +351,7 @@ public class CommitLog {
} }
} }
int readLength = calMsgLength(bodyLen, topicLen, propertiesLength); int readLength = calMsgLength(sysFlag, bodyLen, topicLen, propertiesLength);
if (totalSize != readLength) { if (totalSize != readLength) {
doNothingForDeadCode(reconsumeTimes); doNothingForDeadCode(reconsumeTimes);
doNothingForDeadCode(flag); doNothingForDeadCode(flag);
...@@ -372,7 +384,9 @@ public class CommitLog { ...@@ -372,7 +384,9 @@ public class CommitLog {
return new DispatchRequest(-1, false /* success */); return new DispatchRequest(-1, false /* success */);
} }
protected static int calMsgLength(int bodyLength, int topicLength, int propertiesLength) { protected static int calMsgLength(int sysFlag, int bodyLength, int topicLength, int propertiesLength) {
int bornhostLength = (sysFlag & MessageSysFlag.BORNHOST_V6_FLAG) == 0 ? 8 : 20;
int storehostAddressLength = (sysFlag & MessageSysFlag.STOREHOSTADDRESS_V6_FLAG) == 0 ? 8 : 20;
final int msgLen = 4 //TOTALSIZE final int msgLen = 4 //TOTALSIZE
+ 4 //MAGICCODE + 4 //MAGICCODE
+ 4 //BODYCRC + 4 //BODYCRC
...@@ -382,9 +396,9 @@ public class CommitLog { ...@@ -382,9 +396,9 @@ public class CommitLog {
+ 8 //PHYSICALOFFSET + 8 //PHYSICALOFFSET
+ 4 //SYSFLAG + 4 //SYSFLAG
+ 8 //BORNTIMESTAMP + 8 //BORNTIMESTAMP
+ 8 //BORNHOST + bornhostLength //BORNHOST
+ 8 //STORETIMESTAMP + 8 //STORETIMESTAMP
+ 8 //STOREHOSTADDRESS + storehostAddressLength //STOREHOSTADDRESS
+ 4 //RECONSUMETIMES + 4 //RECONSUMETIMES
+ 8 //Prepared Transaction Offset + 8 //Prepared Transaction Offset
+ 4 + (bodyLength > 0 ? bodyLength : 0) //BODY + 4 + (bodyLength > 0 ? bodyLength : 0) //BODY
...@@ -496,7 +510,10 @@ public class CommitLog { ...@@ -496,7 +510,10 @@ public class CommitLog {
return false; return false;
} }
long storeTimestamp = byteBuffer.getLong(MessageDecoder.MESSAGE_STORE_TIMESTAMP_POSTION); int sysFlag = byteBuffer.getInt(MessageDecoder.SYSFLAG_POSITION);
int bornhostLength = (sysFlag & MessageSysFlag.BORNHOST_V6_FLAG) == 0 ? 8 : 20;
int msgStoreTimePos = 4 + 4 + 4 + 4 + 4 + 8 + 8 + 4 + 8 + bornhostLength;
long storeTimestamp = byteBuffer.getLong(msgStoreTimePos);
if (0 == storeTimestamp) { if (0 == storeTimestamp) {
return false; return false;
} }
...@@ -569,7 +586,18 @@ public class CommitLog { ...@@ -569,7 +586,18 @@ public class CommitLog {
} }
} }
long elapsedTimeInLock = 0; InetSocketAddress bornSocketAddress = (InetSocketAddress) msg.getBornHost();
if (bornSocketAddress.getAddress() instanceof Inet6Address) {
msg.setBornHostV6Flag();
}
InetSocketAddress storeSocketAddress = (InetSocketAddress) msg.getStoreHost();
if (storeSocketAddress.getAddress() instanceof Inet6Address) {
msg.setStoreHostAddressV6Flag();
}
long eclipsedTimeInLock = 0;
MappedFile unlockMappedFile = null; MappedFile unlockMappedFile = null;
MappedFile mappedFile = this.mappedFileQueue.getLastMappedFile(); MappedFile mappedFile = this.mappedFileQueue.getLastMappedFile();
...@@ -619,14 +647,14 @@ public class CommitLog { ...@@ -619,14 +647,14 @@ public class CommitLog {
return new PutMessageResult(PutMessageStatus.UNKNOWN_ERROR, result); return new PutMessageResult(PutMessageStatus.UNKNOWN_ERROR, result);
} }
elapsedTimeInLock = this.defaultMessageStore.getSystemClock().now() - beginLockTimestamp; eclipsedTimeInLock = this.defaultMessageStore.getSystemClock().now() - beginLockTimestamp;
beginTimeInLock = 0; beginTimeInLock = 0;
} finally { } finally {
putMessageLock.unlock(); putMessageLock.unlock();
} }
if (elapsedTimeInLock > 500) { if (eclipsedTimeInLock > 500) {
log.warn("[NOTIFYME]putMessage in lock cost time(ms)={}, bodyLength={} AppendMessageResult={}", elapsedTimeInLock, msg.getBody().length, result); log.warn("[NOTIFYME]putMessage in lock cost time(ms)={}, bodyLength={} AppendMessageResult={}", eclipsedTimeInLock, msg.getBody().length, result);
} }
if (null != unlockMappedFile && this.defaultMessageStore.getMessageStoreConfig().isWarmMapedFileEnable()) { if (null != unlockMappedFile && this.defaultMessageStore.getMessageStoreConfig().isWarmMapedFileEnable()) {
...@@ -714,7 +742,17 @@ public class CommitLog { ...@@ -714,7 +742,17 @@ public class CommitLog {
return new PutMessageResult(PutMessageStatus.MESSAGE_ILLEGAL, null); return new PutMessageResult(PutMessageStatus.MESSAGE_ILLEGAL, null);
} }
long elapsedTimeInLock = 0; InetSocketAddress bornSocketAddress = (InetSocketAddress) messageExtBatch.getBornHost();
if (bornSocketAddress.getAddress() instanceof Inet6Address) {
messageExtBatch.setBornHostV6Flag();
}
InetSocketAddress storeSocketAddress = (InetSocketAddress) messageExtBatch.getStoreHost();
if (storeSocketAddress.getAddress() instanceof Inet6Address) {
messageExtBatch.setStoreHostAddressV6Flag();
}
long eclipsedTimeInLock = 0;
MappedFile unlockMappedFile = null; MappedFile unlockMappedFile = null;
MappedFile mappedFile = this.mappedFileQueue.getLastMappedFile(); MappedFile mappedFile = this.mappedFileQueue.getLastMappedFile();
...@@ -769,14 +807,14 @@ public class CommitLog { ...@@ -769,14 +807,14 @@ public class CommitLog {
return new PutMessageResult(PutMessageStatus.UNKNOWN_ERROR, result); return new PutMessageResult(PutMessageStatus.UNKNOWN_ERROR, result);
} }
elapsedTimeInLock = this.defaultMessageStore.getSystemClock().now() - beginLockTimestamp; eclipsedTimeInLock = this.defaultMessageStore.getSystemClock().now() - beginLockTimestamp;
beginTimeInLock = 0; beginTimeInLock = 0;
} finally { } finally {
putMessageLock.unlock(); putMessageLock.unlock();
} }
if (elapsedTimeInLock > 500) { if (eclipsedTimeInLock > 500) {
log.warn("[NOTIFYME]putMessages in lock cost time(ms)={}, bodyLength={} AppendMessageResult={}", elapsedTimeInLock, messageExtBatch.getBody().length, result); log.warn("[NOTIFYME]putMessages in lock cost time(ms)={}, bodyLength={} AppendMessageResult={}", eclipsedTimeInLock, messageExtBatch.getBody().length, result);
} }
if (null != unlockMappedFile && this.defaultMessageStore.getMessageStoreConfig().isWarmMapedFileEnable()) { if (null != unlockMappedFile && this.defaultMessageStore.getMessageStoreConfig().isWarmMapedFileEnable()) {
...@@ -804,7 +842,10 @@ public class CommitLog { ...@@ -804,7 +842,10 @@ public class CommitLog {
SelectMappedBufferResult result = this.getMessage(offset, size); SelectMappedBufferResult result = this.getMessage(offset, size);
if (null != result) { if (null != result) {
try { try {
return result.getByteBuffer().getLong(MessageDecoder.MESSAGE_STORE_TIMESTAMP_POSTION); int sysFlag = result.getByteBuffer().getInt(MessageDecoder.SYSFLAG_POSITION);
int bornhostLength = (sysFlag & MessageSysFlag.BORNHOST_V6_FLAG) == 0 ? 8 : 20;
int msgStoreTimePos = 4 + 4 + 4 + 4 + 4 + 8 + 8 + 4 + 8 + bornhostLength;
return result.getByteBuffer().getLong(msgStoreTimePos);
} finally { } finally {
result.release(); result.release();
} }
...@@ -1170,6 +1211,7 @@ public class CommitLog { ...@@ -1170,6 +1211,7 @@ public class CommitLog {
// File at the end of the minimum fixed length empty // File at the end of the minimum fixed length empty
private static final int END_FILE_MIN_BLANK_LENGTH = 4 + 4; private static final int END_FILE_MIN_BLANK_LENGTH = 4 + 4;
private final ByteBuffer msgIdMemory; private final ByteBuffer msgIdMemory;
private final ByteBuffer msgIdV6Memory;
// Store the message content // Store the message content
private final ByteBuffer msgStoreItemMemory; private final ByteBuffer msgStoreItemMemory;
// The maximum length of the message // The maximum length of the message
...@@ -1179,10 +1221,9 @@ public class CommitLog { ...@@ -1179,10 +1221,9 @@ public class CommitLog {
private final StringBuilder msgIdBuilder = new StringBuilder(); private final StringBuilder msgIdBuilder = new StringBuilder();
private final ByteBuffer hostHolder = ByteBuffer.allocate(8);
DefaultAppendMessageCallback(final int size) { DefaultAppendMessageCallback(final int size) {
this.msgIdMemory = ByteBuffer.allocate(MessageDecoder.MSG_ID_LENGTH); 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.msgStoreItemMemory = ByteBuffer.allocate(size + END_FILE_MIN_BLANK_LENGTH);
this.maxMessageSize = size; this.maxMessageSize = size;
} }
...@@ -1198,8 +1239,20 @@ public class CommitLog { ...@@ -1198,8 +1239,20 @@ public class CommitLog {
// PHY OFFSET // PHY OFFSET
long wroteOffset = fileFromOffset + byteBuffer.position(); long wroteOffset = fileFromOffset + byteBuffer.position();
this.resetByteBuffer(hostHolder, 8); int sysflag = msgInner.getSysFlag();
String msgId = MessageDecoder.createMessageId(this.msgIdMemory, msgInner.getStoreHostBytes(hostHolder), wroteOffset);
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);
this.resetByteBuffer(storeHostHolder, storeHostLength);
String msgId;
if ((sysflag & MessageSysFlag.STOREHOSTADDRESS_V6_FLAG) == 0) {
msgId = MessageDecoder.createMessageId(this.msgIdMemory, msgInner.getStoreHostBytes(storeHostHolder), wroteOffset);
} else {
msgId = MessageDecoder.createMessageId(this.msgIdV6Memory, msgInner.getStoreHostBytes(storeHostHolder), wroteOffset);
}
// Record ConsumeQueue information // Record ConsumeQueue information
keyBuilder.setLength(0); keyBuilder.setLength(0);
...@@ -1246,7 +1299,7 @@ public class CommitLog { ...@@ -1246,7 +1299,7 @@ public class CommitLog {
final int bodyLength = msgInner.getBody() == null ? 0 : msgInner.getBody().length; final int bodyLength = msgInner.getBody() == null ? 0 : msgInner.getBody().length;
final int msgLen = calMsgLength(bodyLength, topicLength, propertiesLength); final int msgLen = calMsgLength(msgInner.getSysFlag(), bodyLength, topicLength, propertiesLength);
// Exceeds the maximum message // Exceeds the maximum message
if (msgLen > this.maxMessageSize) { if (msgLen > this.maxMessageSize) {
...@@ -1291,14 +1344,13 @@ public class CommitLog { ...@@ -1291,14 +1344,13 @@ public class CommitLog {
// 9 BORNTIMESTAMP // 9 BORNTIMESTAMP
this.msgStoreItemMemory.putLong(msgInner.getBornTimestamp()); this.msgStoreItemMemory.putLong(msgInner.getBornTimestamp());
// 10 BORNHOST // 10 BORNHOST
this.resetByteBuffer(hostHolder, 8); this.resetByteBuffer(bornHostHolder, bornHostLength);
this.msgStoreItemMemory.put(msgInner.getBornHostBytes(hostHolder)); this.msgStoreItemMemory.put(msgInner.getBornHostBytes(bornHostHolder));
// 11 STORETIMESTAMP // 11 STORETIMESTAMP
this.msgStoreItemMemory.putLong(msgInner.getStoreTimestamp()); this.msgStoreItemMemory.putLong(msgInner.getStoreTimestamp());
// 12 STOREHOSTADDRESS // 12 STOREHOSTADDRESS
this.resetByteBuffer(hostHolder, 8); this.resetByteBuffer(storeHostHolder, storeHostLength);
this.msgStoreItemMemory.put(msgInner.getStoreHostBytes(hostHolder)); this.msgStoreItemMemory.put(msgInner.getStoreHostBytes(storeHostHolder));
//this.msgBatchMemory.put(msgInner.getStoreHostBytes());
// 13 RECONSUMETIMES // 13 RECONSUMETIMES
this.msgStoreItemMemory.putInt(msgInner.getReconsumeTimes()); this.msgStoreItemMemory.putInt(msgInner.getReconsumeTimes());
// 14 Prepared Transaction Offset // 14 Prepared Transaction Offset
...@@ -1359,8 +1411,13 @@ public class CommitLog { ...@@ -1359,8 +1411,13 @@ public class CommitLog {
msgIdBuilder.setLength(0); msgIdBuilder.setLength(0);
final long beginTimeMills = CommitLog.this.defaultMessageStore.now(); final long beginTimeMills = CommitLog.this.defaultMessageStore.now();
ByteBuffer messagesByteBuff = messageExtBatch.getEncodedBuff(); ByteBuffer messagesByteBuff = messageExtBatch.getEncodedBuff();
this.resetByteBuffer(hostHolder, 8);
ByteBuffer storeHostBytes = messageExtBatch.getStoreHostBytes(hostHolder); int sysFlag = messageExtBatch.getSysFlag();
int storeHostLength = (sysFlag & MessageSysFlag.STOREHOSTADDRESS_V6_FLAG) == 0 ? 4 + 4 : 16 + 4;
ByteBuffer storeHostHolder = ByteBuffer.allocate(storeHostLength);
this.resetByteBuffer(storeHostHolder, storeHostLength);
ByteBuffer storeHostBytes = messageExtBatch.getStoreHostBytes(storeHostHolder);
messagesByteBuff.mark(); messagesByteBuff.mark();
while (messagesByteBuff.hasRemaining()) { while (messagesByteBuff.hasRemaining()) {
// 1 TOTALSIZE // 1 TOTALSIZE
...@@ -1396,7 +1453,13 @@ public class CommitLog { ...@@ -1396,7 +1453,13 @@ public class CommitLog {
messagesByteBuff.putLong(wroteOffset + totalMsgLen - msgLen); messagesByteBuff.putLong(wroteOffset + totalMsgLen - msgLen);
storeHostBytes.rewind(); storeHostBytes.rewind();
String msgId = MessageDecoder.createMessageId(this.msgIdMemory, storeHostBytes, wroteOffset + totalMsgLen - msgLen); String msgId;
if ((sysFlag & MessageSysFlag.STOREHOSTADDRESS_V6_FLAG) == 0) {
msgId = MessageDecoder.createMessageId(this.msgIdMemory, storeHostBytes, wroteOffset + totalMsgLen - msgLen);
} else {
msgId = MessageDecoder.createMessageId(this.msgIdV6Memory, storeHostBytes, wroteOffset + totalMsgLen - msgLen);
}
if (msgIdBuilder.length() > 0) { if (msgIdBuilder.length() > 0) {
msgIdBuilder.append(',').append(msgId); msgIdBuilder.append(',').append(msgId);
} else { } else {
...@@ -1432,8 +1495,6 @@ public class CommitLog { ...@@ -1432,8 +1495,6 @@ public class CommitLog {
// The maximum length of the message // The maximum length of the message
private final int maxMessageSize; private final int maxMessageSize;
private final ByteBuffer hostHolder = ByteBuffer.allocate(8);
MessageExtBatchEncoder(final int size) { MessageExtBatchEncoder(final int size) {
this.msgBatchMemory = ByteBuffer.allocateDirect(size); this.msgBatchMemory = ByteBuffer.allocateDirect(size);
this.maxMessageSize = size; this.maxMessageSize = size;
...@@ -1443,6 +1504,13 @@ public class CommitLog { ...@@ -1443,6 +1504,13 @@ public class CommitLog {
msgBatchMemory.clear(); //not thread-safe msgBatchMemory.clear(); //not thread-safe
int totalMsgLen = 0; int totalMsgLen = 0;
ByteBuffer messagesByteBuff = messageExtBatch.wrap(); ByteBuffer messagesByteBuff = messageExtBatch.wrap();
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()) { while (messagesByteBuff.hasRemaining()) {
// 1 TOTALSIZE // 1 TOTALSIZE
messagesByteBuff.getInt(); messagesByteBuff.getInt();
...@@ -1466,7 +1534,7 @@ public class CommitLog { ...@@ -1466,7 +1534,7 @@ public class CommitLog {
final int topicLength = topicData.length; final int topicLength = topicData.length;
final int msgLen = calMsgLength(bodyLen, topicLength, propertiesLen); final int msgLen = calMsgLength(messageExtBatch.getSysFlag(), bodyLen, topicLength, propertiesLen);
// Exceeds the maximum message // Exceeds the maximum message
if (msgLen > this.maxMessageSize) { if (msgLen > this.maxMessageSize) {
...@@ -1500,13 +1568,13 @@ public class CommitLog { ...@@ -1500,13 +1568,13 @@ public class CommitLog {
// 9 BORNTIMESTAMP // 9 BORNTIMESTAMP
this.msgBatchMemory.putLong(messageExtBatch.getBornTimestamp()); this.msgBatchMemory.putLong(messageExtBatch.getBornTimestamp());
// 10 BORNHOST // 10 BORNHOST
this.resetByteBuffer(hostHolder, 8); this.resetByteBuffer(bornHostHolder, bornHostLength);
this.msgBatchMemory.put(messageExtBatch.getBornHostBytes(hostHolder)); this.msgBatchMemory.put(messageExtBatch.getBornHostBytes(bornHostHolder));
// 11 STORETIMESTAMP // 11 STORETIMESTAMP
this.msgBatchMemory.putLong(messageExtBatch.getStoreTimestamp()); this.msgBatchMemory.putLong(messageExtBatch.getStoreTimestamp());
// 12 STOREHOSTADDRESS // 12 STOREHOSTADDRESS
this.resetByteBuffer(hostHolder, 8); this.resetByteBuffer(storeHostHolder, storeHostLength);
this.msgBatchMemory.put(messageExtBatch.getStoreHostBytes(hostHolder)); this.msgBatchMemory.put(messageExtBatch.getStoreHostBytes(storeHostHolder));
// 13 RECONSUMETIMES // 13 RECONSUMETIMES
this.msgBatchMemory.putInt(messageExtBatch.getReconsumeTimes()); this.msgBatchMemory.putInt(messageExtBatch.getReconsumeTimes());
// 14 Prepared Transaction Offset, batch does not support transaction // 14 Prepared Transaction Offset, batch does not support transaction
......
...@@ -19,6 +19,8 @@ package org.apache.rocketmq.store; ...@@ -19,6 +19,8 @@ package org.apache.rocketmq.store;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.RandomAccessFile; import java.io.RandomAccessFile;
import java.net.Inet6Address;
import java.net.InetSocketAddress;
import java.net.SocketAddress; import java.net.SocketAddress;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.nio.channels.FileLock; import java.nio.channels.FileLock;
...@@ -285,8 +287,6 @@ public class DefaultMessageStore implements MessageStore { ...@@ -285,8 +287,6 @@ public class DefaultMessageStore implements MessageStore {
this.shutdown = false; this.shutdown = false;
} }
public void shutdown() { public void shutdown() {
if (!this.shutdown) { if (!this.shutdown) {
this.shutdown = true; this.shutdown = true;
...@@ -469,7 +469,7 @@ public class DefaultMessageStore implements MessageStore { ...@@ -469,7 +469,7 @@ public class DefaultMessageStore implements MessageStore {
long diff = this.systemClock.now() - begin; long diff = this.systemClock.now() - begin;
return diff < 10000000 return diff < 10000000
&& diff > this.messageStoreConfig.getOsPageCacheBusyTimeOutMills(); && diff > this.messageStoreConfig.getOsPageCacheBusyTimeOutMills();
} }
@Override @Override
...@@ -1042,7 +1042,9 @@ public class DefaultMessageStore implements MessageStore { ...@@ -1042,7 +1042,9 @@ public class DefaultMessageStore implements MessageStore {
int i = 0; int i = 0;
for (; i < bufferConsumeQueue.getSize(); i += ConsumeQueue.CQ_STORE_UNIT_SIZE) { for (; i < bufferConsumeQueue.getSize(); i += ConsumeQueue.CQ_STORE_UNIT_SIZE) {
long offsetPy = bufferConsumeQueue.getByteBuffer().getLong(); long offsetPy = bufferConsumeQueue.getByteBuffer().getLong();
final ByteBuffer msgIdMemory = ByteBuffer.allocate(MessageDecoder.MSG_ID_LENGTH); InetSocketAddress inetSocketAddress = (InetSocketAddress) storeHost;
int msgIdLength = (inetSocketAddress.getAddress() instanceof Inet6Address) ? 16 + 4 + 8 : 4 + 4 + 8;
final ByteBuffer msgIdMemory = ByteBuffer.allocate(msgIdLength);
String msgId = String msgId =
MessageDecoder.createMessageId(msgIdMemory, MessageExt.socketAddress2ByteBuffer(storeHost), offsetPy); MessageDecoder.createMessageId(msgIdMemory, MessageExt.socketAddress2ByteBuffer(storeHost), offsetPy);
messageIds.put(msgId, nextOffset++); messageIds.put(msgId, nextOffset++);
......
...@@ -68,12 +68,11 @@ public class DLedgerCommitLog extends CommitLog { ...@@ -68,12 +68,11 @@ public class DLedgerCommitLog extends CommitLog {
//This offset separate the old commitlog from dledger commitlog //This offset separate the old commitlog from dledger commitlog
private long dividedCommitlogOffset = -1; private long dividedCommitlogOffset = -1;
private boolean isInrecoveringOldCommitlog = false; private boolean isInrecoveringOldCommitlog = false;
public DLedgerCommitLog(final DefaultMessageStore defaultMessageStore) { public DLedgerCommitLog(final DefaultMessageStore defaultMessageStore) {
super(defaultMessageStore); super(defaultMessageStore);
dLedgerConfig = new DLedgerConfig(); dLedgerConfig = new DLedgerConfig();
dLedgerConfig.setEnableDiskForceClean(defaultMessageStore.getMessageStoreConfig().isCleanFileForciblyEnable()); dLedgerConfig.setEnableDiskForceClean(defaultMessageStore.getMessageStoreConfig().isCleanFileForciblyEnable());
dLedgerConfig.setStoreType(DLedgerConfig.FILE); dLedgerConfig.setStoreType(DLedgerConfig.FILE);
dLedgerConfig.setSelfId(defaultMessageStore.getMessageStoreConfig().getdLegerSelfId()); dLedgerConfig.setSelfId(defaultMessageStore.getMessageStoreConfig().getdLegerSelfId());
...@@ -158,8 +157,6 @@ public class DLedgerCommitLog extends CommitLog { ...@@ -158,8 +157,6 @@ public class DLedgerCommitLog extends CommitLog {
log.warn("Should not set confirm offset {} for dleger commitlog", phyOffset); log.warn("Should not set confirm offset {} for dleger commitlog", phyOffset);
} }
@Override @Override
public long remainHowManyDataToCommit() { public long remainHowManyDataToCommit() {
return dLedgerFileList.remainHowManyDataToCommit(); return dLedgerFileList.remainHowManyDataToCommit();
...@@ -180,7 +177,7 @@ public class DLedgerCommitLog extends CommitLog { ...@@ -180,7 +177,7 @@ public class DLedgerCommitLog extends CommitLog {
if (mappedFileQueue.getMappedFiles().isEmpty()) { if (mappedFileQueue.getMappedFiles().isEmpty()) {
refreshConfig(); refreshConfig();
//To prevent too much log in defaultMessageStore //To prevent too much log in defaultMessageStore
return Integer.MAX_VALUE; return Integer.MAX_VALUE;
} else { } else {
disableDeleteDledger(); disableDeleteDledger();
} }
...@@ -201,7 +198,6 @@ public class DLedgerCommitLog extends CommitLog { ...@@ -201,7 +198,6 @@ public class DLedgerCommitLog extends CommitLog {
return 1; return 1;
} }
public SelectMappedBufferResult convertSbr(SelectMmapBufferResult sbr) { public SelectMappedBufferResult convertSbr(SelectMmapBufferResult sbr) {
if (sbr == null) { if (sbr == null) {
return null; return null;
...@@ -232,7 +228,6 @@ public class DLedgerCommitLog extends CommitLog { ...@@ -232,7 +228,6 @@ public class DLedgerCommitLog extends CommitLog {
return this.getData(offset, offset == 0); return this.getData(offset, offset == 0);
} }
@Override @Override
public SelectMappedBufferResult getData(final long offset, final boolean returnFirstOnNotFound) { public SelectMappedBufferResult getData(final long offset, final boolean returnFirstOnNotFound) {
if (offset < dividedCommitlogOffset) { if (offset < dividedCommitlogOffset) {
...@@ -246,7 +241,7 @@ public class DLedgerCommitLog extends CommitLog { ...@@ -246,7 +241,7 @@ public class DLedgerCommitLog extends CommitLog {
if (mappedFile != null) { if (mappedFile != null) {
int pos = (int) (offset % mappedFileSize); int pos = (int) (offset % mappedFileSize);
SelectMmapBufferResult sbr = mappedFile.selectMappedBuffer(pos); SelectMmapBufferResult sbr = mappedFile.selectMappedBuffer(pos);
return convertSbr(truncate(sbr)); return convertSbr(truncate(sbr));
} }
return null; return null;
...@@ -278,7 +273,7 @@ public class DLedgerCommitLog extends CommitLog { ...@@ -278,7 +273,7 @@ public class DLedgerCommitLog extends CommitLog {
if (mappedFile == null) { if (mappedFile == null) {
return; return;
} }
ByteBuffer byteBuffer = mappedFile.sliceByteBuffer(); ByteBuffer byteBuffer = mappedFile.sliceByteBuffer();
byteBuffer.position(mappedFile.getWrotePosition()); byteBuffer.position(mappedFile.getWrotePosition());
boolean needWriteMagicCode = true; boolean needWriteMagicCode = true;
// 1 TOTAL SIZE // 1 TOTAL SIZE
...@@ -311,7 +306,7 @@ public class DLedgerCommitLog extends CommitLog { ...@@ -311,7 +306,7 @@ public class DLedgerCommitLog extends CommitLog {
} }
@Override @Override
public void recoverAbnormally(long maxPhyOffsetOfConsumeQueue) { public void recoverAbnormally(long maxPhyOffsetOfConsumeQueue) {
recover(maxPhyOffsetOfConsumeQueue); recover(maxPhyOffsetOfConsumeQueue);
} }
...@@ -329,9 +324,9 @@ public class DLedgerCommitLog extends CommitLog { ...@@ -329,9 +324,9 @@ public class DLedgerCommitLog extends CommitLog {
try { try {
int bodyOffset = DLedgerEntry.BODY_OFFSET; int bodyOffset = DLedgerEntry.BODY_OFFSET;
int pos = byteBuffer.position(); int pos = byteBuffer.position();
int magic = byteBuffer.getInt(); int magic = byteBuffer.getInt();
//In dledger, this field is size, it must be gt 0, so it could prevent collision //In dledger, this field is size, it must be gt 0, so it could prevent collision
int magicOld = byteBuffer.getInt(); int magicOld = byteBuffer.getInt();
if (magicOld == CommitLog.BLANK_MAGIC_CODE || magicOld == CommitLog.MESSAGE_MAGIC_CODE) { if (magicOld == CommitLog.BLANK_MAGIC_CODE || magicOld == CommitLog.MESSAGE_MAGIC_CODE) {
byteBuffer.position(pos); byteBuffer.position(pos);
return super.checkMessageAndReturnSize(byteBuffer, checkCRC, readBody); return super.checkMessageAndReturnSize(byteBuffer, checkCRC, readBody);
...@@ -409,10 +404,10 @@ public class DLedgerCommitLog extends CommitLog { ...@@ -409,10 +404,10 @@ public class DLedgerCommitLog extends CommitLog {
long elapsedTimeInLock; long elapsedTimeInLock;
long queueOffset; long queueOffset;
try { try {
beginTimeInDledgerLock = this.defaultMessageStore.getSystemClock().now(); beginTimeInDledgerLock = this.defaultMessageStore.getSystemClock().now();
encodeResult = this.messageSerializer.serialize(msg); encodeResult = this.messageSerializer.serialize(msg);
queueOffset = topicQueueTable.get(encodeResult.queueOffsetKey); queueOffset = topicQueueTable.get(encodeResult.queueOffsetKey);
if (encodeResult.status != AppendMessageStatus.PUT_OK) { if (encodeResult.status != AppendMessageStatus.PUT_OK) {
return new PutMessageResult(PutMessageStatus.MESSAGE_ILLEGAL, new AppendMessageResult(encodeResult.status)); return new PutMessageResult(PutMessageStatus.MESSAGE_ILLEGAL, new AppendMessageResult(encodeResult.status));
} }
AppendEntryRequest request = new AppendEntryRequest(); AppendEntryRequest request = new AppendEntryRequest();
...@@ -423,8 +418,11 @@ public class DLedgerCommitLog extends CommitLog { ...@@ -423,8 +418,11 @@ public class DLedgerCommitLog extends CommitLog {
if (dledgerFuture.getPos() == -1) { if (dledgerFuture.getPos() == -1) {
return new PutMessageResult(PutMessageStatus.OS_PAGECACHE_BUSY, new AppendMessageResult(AppendMessageStatus.UNKNOWN_ERROR)); return new PutMessageResult(PutMessageStatus.OS_PAGECACHE_BUSY, new AppendMessageResult(AppendMessageStatus.UNKNOWN_ERROR));
} }
long wroteOffset = dledgerFuture.getPos() + DLedgerEntry.BODY_OFFSET; long wroteOffset = dledgerFuture.getPos() + DLedgerEntry.BODY_OFFSET;
ByteBuffer buffer = ByteBuffer.allocate(MessageDecoder.MSG_ID_LENGTH);
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); String msgId = MessageDecoder.createMessageId(buffer, msg.getStoreHostBytes(), wroteOffset);
elapsedTimeInLock = this.defaultMessageStore.getSystemClock().now() - beginTimeInDledgerLock; 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.data.length, msgId, System.currentTimeMillis(), queueOffset, elapsedTimeInLock);
...@@ -491,8 +489,6 @@ public class DLedgerCommitLog extends CommitLog { ...@@ -491,8 +489,6 @@ public class DLedgerCommitLog extends CommitLog {
return new PutMessageResult(PutMessageStatus.MESSAGE_ILLEGAL, null); return new PutMessageResult(PutMessageStatus.MESSAGE_ILLEGAL, null);
} }
@Override @Override
public SelectMappedBufferResult getMessage(final long offset, final int size) { public SelectMappedBufferResult getMessage(final long offset, final int size) {
if (offset < dividedCommitlogOffset) { if (offset < dividedCommitlogOffset) {
...@@ -502,7 +498,7 @@ public class DLedgerCommitLog extends CommitLog { ...@@ -502,7 +498,7 @@ public class DLedgerCommitLog extends CommitLog {
MmapFile mappedFile = this.dLedgerFileList.findMappedFileByOffset(offset, offset == 0); MmapFile mappedFile = this.dLedgerFileList.findMappedFileByOffset(offset, offset == 0);
if (mappedFile != null) { if (mappedFile != null) {
int pos = (int) (offset % mappedFileSize); int pos = (int) (offset % mappedFileSize);
return convertSbr(mappedFile.selectMappedBuffer(pos, size)); return convertSbr(mappedFile.selectMappedBuffer(pos, size));
} }
return null; return null;
} }
...@@ -559,6 +555,7 @@ public class DLedgerCommitLog extends CommitLog { ...@@ -559,6 +555,7 @@ public class DLedgerCommitLog extends CommitLog {
private String queueOffsetKey; private String queueOffsetKey;
private byte[] data; private byte[] data;
private AppendMessageStatus status; private AppendMessageStatus status;
public EncodeResult(AppendMessageStatus status, byte[] data, String queueOffsetKey) { public EncodeResult(AppendMessageStatus status, byte[] data, String queueOffsetKey) {
this.data = data; this.data = data;
this.status = status; this.status = status;
...@@ -570,6 +567,7 @@ public class DLedgerCommitLog extends CommitLog { ...@@ -570,6 +567,7 @@ public class DLedgerCommitLog extends CommitLog {
// File at the end of the minimum fixed length empty // File at the end of the minimum fixed length empty
private static final int END_FILE_MIN_BLANK_LENGTH = 4 + 4; private static final int END_FILE_MIN_BLANK_LENGTH = 4 + 4;
private final ByteBuffer msgIdMemory; private final ByteBuffer msgIdMemory;
private final ByteBuffer msgIdV6Memory;
// Store the message content // Store the message content
private final ByteBuffer msgStoreItemMemory; private final ByteBuffer msgStoreItemMemory;
// The maximum length of the message // The maximum length of the message
...@@ -579,10 +577,11 @@ public class DLedgerCommitLog extends CommitLog { ...@@ -579,10 +577,11 @@ public class DLedgerCommitLog extends CommitLog {
private final StringBuilder msgIdBuilder = new StringBuilder(); private final StringBuilder msgIdBuilder = new StringBuilder();
private final ByteBuffer hostHolder = ByteBuffer.allocate(8); // private final ByteBuffer hostHolder = ByteBuffer.allocate(8);
MessageSerializer(final int size) { MessageSerializer(final int size) {
this.msgIdMemory = ByteBuffer.allocate(MessageDecoder.MSG_ID_LENGTH); 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.msgStoreItemMemory = ByteBuffer.allocate(size + END_FILE_MIN_BLANK_LENGTH);
this.maxMessageSize = size; this.maxMessageSize = size;
} }
...@@ -597,7 +596,13 @@ public class DLedgerCommitLog extends CommitLog { ...@@ -597,7 +596,13 @@ public class DLedgerCommitLog extends CommitLog {
// PHY OFFSET // PHY OFFSET
long wroteOffset = 0; long wroteOffset = 0;
this.resetByteBuffer(hostHolder, 8); int sysflag = msgInner.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);
// Record ConsumeQueue information // Record ConsumeQueue information
keyBuilder.setLength(0); keyBuilder.setLength(0);
keyBuilder.append(msgInner.getTopic()); keyBuilder.append(msgInner.getTopic());
...@@ -644,7 +649,7 @@ public class DLedgerCommitLog extends CommitLog { ...@@ -644,7 +649,7 @@ public class DLedgerCommitLog extends CommitLog {
final int bodyLength = msgInner.getBody() == null ? 0 : msgInner.getBody().length; final int bodyLength = msgInner.getBody() == null ? 0 : msgInner.getBody().length;
final int msgLen = calMsgLength(bodyLength, topicLength, propertiesLength); final int msgLen = calMsgLength(msgInner.getSysFlag(), bodyLength, topicLength, propertiesLength);
// Exceeds the maximum message // Exceeds the maximum message
if (msgLen > this.maxMessageSize) { if (msgLen > this.maxMessageSize) {
...@@ -673,13 +678,13 @@ public class DLedgerCommitLog extends CommitLog { ...@@ -673,13 +678,13 @@ public class DLedgerCommitLog extends CommitLog {
// 9 BORNTIMESTAMP // 9 BORNTIMESTAMP
this.msgStoreItemMemory.putLong(msgInner.getBornTimestamp()); this.msgStoreItemMemory.putLong(msgInner.getBornTimestamp());
// 10 BORNHOST // 10 BORNHOST
this.resetByteBuffer(hostHolder, 8); this.resetByteBuffer(bornHostHolder, bornHostLength);
this.msgStoreItemMemory.put(msgInner.getBornHostBytes(hostHolder)); this.msgStoreItemMemory.put(msgInner.getBornHostBytes(bornHostHolder));
// 11 STORETIMESTAMP // 11 STORETIMESTAMP
this.msgStoreItemMemory.putLong(msgInner.getStoreTimestamp()); this.msgStoreItemMemory.putLong(msgInner.getStoreTimestamp());
// 12 STOREHOSTADDRESS // 12 STOREHOSTADDRESS
this.resetByteBuffer(hostHolder, 8); this.resetByteBuffer(storeHostHolder, storeHostLength);
this.msgStoreItemMemory.put(msgInner.getStoreHostBytes(hostHolder)); this.msgStoreItemMemory.put(msgInner.getStoreHostBytes(storeHostHolder));
//this.msgBatchMemory.put(msgInner.getStoreHostBytes()); //this.msgBatchMemory.put(msgInner.getStoreHostBytes());
// 13 RECONSUMETIMES // 13 RECONSUMETIMES
this.msgStoreItemMemory.putInt(msgInner.getReconsumeTimes()); this.msgStoreItemMemory.putInt(msgInner.getReconsumeTimes());
...@@ -714,6 +719,7 @@ public class DLedgerCommitLog extends CommitLog { ...@@ -714,6 +719,7 @@ public class DLedgerCommitLog extends CommitLog {
public static class DLedgerSelectMappedBufferResult extends SelectMappedBufferResult { public static class DLedgerSelectMappedBufferResult extends SelectMappedBufferResult {
private SelectMmapBufferResult sbr; private SelectMmapBufferResult sbr;
public DLedgerSelectMappedBufferResult(SelectMmapBufferResult sbr) { public DLedgerSelectMappedBufferResult(SelectMmapBufferResult sbr) {
super(sbr.getStartOffset(), sbr.getByteBuffer(), sbr.getSize(), null); super(sbr.getStartOffset(), sbr.getByteBuffer(), sbr.getSize(), null);
this.sbr = sbr; this.sbr = sbr;
......
...@@ -280,7 +280,9 @@ public class HAService { ...@@ -280,7 +280,9 @@ public class HAService {
if (!this.requestsRead.isEmpty()) { if (!this.requestsRead.isEmpty()) {
for (CommitLog.GroupCommitRequest req : this.requestsRead) { for (CommitLog.GroupCommitRequest req : this.requestsRead) {
boolean transferOK = HAService.this.push2SlaveMaxOffset.get() >= req.getNextOffset(); boolean transferOK = HAService.this.push2SlaveMaxOffset.get() >= req.getNextOffset();
for (int i = 0; !transferOK && i < 5; i++) { long waitUntilWhen = HAService.this.defaultMessageStore.getSystemClock().now()
+ HAService.this.defaultMessageStore.getMessageStoreConfig().getSyncFlushTimeout();
while (!transferOK && HAService.this.defaultMessageStore.getSystemClock().now() < waitUntilWhen) {
this.notifyTransferObject.waitForRunning(1000); this.notifyTransferObject.waitForRunning(1000);
transferOK = HAService.this.push2SlaveMaxOffset.get() >= req.getNextOffset(); transferOK = HAService.this.push2SlaveMaxOffset.get() >= req.getNextOffset();
} }
......
...@@ -97,6 +97,43 @@ public class AppendCallbackTest { ...@@ -97,6 +97,43 @@ public class AppendCallbackTest {
assertTrue(result.getMsgId().length() > 0); //should have already constructed some message ids assertTrue(result.getMsgId().length() > 0); //should have already constructed some message ids
} }
@Test
public void testAppendIPv6HostMessageBatchEndOfFile() throws Exception {
List<Message> messages = new ArrayList<>();
String topic = "test-topic";
int queue = 0;
for (int i = 0; i < 10; i++) {
Message msg = new Message();
msg.setBody("body".getBytes());
msg.setTopic(topic);
msg.setTags("abc");
messages.add(msg);
}
MessageExtBatch messageExtBatch = new MessageExtBatch();
messageExtBatch.setTopic(topic);
messageExtBatch.setQueueId(queue);
messageExtBatch.setBornTimestamp(System.currentTimeMillis());
messageExtBatch.setMsgId("24084004018081003FAA1DDE2B3F898A00002A9F0000000000000CA0");
messageExtBatch.setSysFlag(0);
messageExtBatch.setBornHostV6Flag();
messageExtBatch.setStoreHostAddressV6Flag();
messageExtBatch.setBornHost(new InetSocketAddress("1050:0000:0000:0000:0005:0600:300c:326b", 123));
messageExtBatch.setStoreHost(new InetSocketAddress("::1", 124));
messageExtBatch.setBody(MessageDecoder.encodeMessages(messages));
messageExtBatch.setEncodedBuff(batchEncoder.encode(messageExtBatch));
ByteBuffer buff = ByteBuffer.allocate(1024 * 10);
//encounter end of file when append half of the data
AppendMessageResult result = callback.doAppend(0, buff, 1000, messageExtBatch);
assertEquals(AppendMessageStatus.END_OF_FILE, result.getStatus());
assertEquals(0, result.getWroteOffset());
assertEquals(0, result.getLogicsOffset());
assertEquals(1000, result.getWroteBytes());
assertEquals(8, buff.position()); //write blank size and magic value
assertTrue(result.getMsgId().length() > 0); //should have already constructed some message ids
}
@Test @Test
public void testAppendMessageBatchSucc() throws Exception { public void testAppendMessageBatchSucc() throws Exception {
List<Message> messages = new ArrayList<>(); List<Message> messages = new ArrayList<>();
...@@ -153,4 +190,64 @@ public class AppendCallbackTest { ...@@ -153,4 +190,64 @@ public class AppendCallbackTest {
} }
@Test
public void testAppendIPv6HostMessageBatchSucc() throws Exception {
List<Message> messages = new ArrayList<>();
String topic = "test-topic";
int queue = 0;
for (int i = 0; i < 10; i++) {
Message msg = new Message();
msg.setBody("body".getBytes());
msg.setTopic(topic);
msg.setTags("abc");
messages.add(msg);
}
MessageExtBatch messageExtBatch = new MessageExtBatch();
messageExtBatch.setTopic(topic);
messageExtBatch.setQueueId(queue);
messageExtBatch.setBornTimestamp(System.currentTimeMillis());
messageExtBatch.setMsgId("24084004018081003FAA1DDE2B3F898A00002A9F0000000000000CA0");
messageExtBatch.setSysFlag(0);
messageExtBatch.setBornHostV6Flag();
messageExtBatch.setStoreHostAddressV6Flag();
messageExtBatch.setBornHost(new InetSocketAddress("1050:0000:0000:0000:0005:0600:300c:326b", 123));
messageExtBatch.setStoreHost(new InetSocketAddress("::1", 124));
messageExtBatch.setBody(MessageDecoder.encodeMessages(messages));
messageExtBatch.setEncodedBuff(batchEncoder.encode(messageExtBatch));
ByteBuffer buff = ByteBuffer.allocate(1024 * 10);
AppendMessageResult allresult = callback.doAppend(0, buff, 1024 * 10, messageExtBatch);
assertEquals(AppendMessageStatus.PUT_OK, allresult.getStatus());
assertEquals(0, allresult.getWroteOffset());
assertEquals(0, allresult.getLogicsOffset());
assertEquals(buff.position(), allresult.getWroteBytes());
assertEquals(messages.size(), allresult.getMsgNum());
Set<String> msgIds = new HashSet<>();
for (String msgId : allresult.getMsgId().split(",")) {
assertEquals(56, msgId.length());
msgIds.add(msgId);
}
assertEquals(messages.size(), msgIds.size());
List<MessageExt> decodeMsgs = MessageDecoder.decodes((ByteBuffer) buff.flip());
assertEquals(decodeMsgs.size(), decodeMsgs.size());
long queueOffset = decodeMsgs.get(0).getQueueOffset();
long storeTimeStamp = decodeMsgs.get(0).getStoreTimestamp();
for (int i = 0; i < messages.size(); i++) {
assertEquals(messages.get(i).getTopic(), decodeMsgs.get(i).getTopic());
assertEquals(new String(messages.get(i).getBody()), new String(decodeMsgs.get(i).getBody()));
assertEquals(messages.get(i).getTags(), decodeMsgs.get(i).getTags());
assertEquals(messageExtBatch.getBornHostNameString(), decodeMsgs.get(i).getBornHostNameString());
assertEquals(messageExtBatch.getBornTimestamp(), decodeMsgs.get(i).getBornTimestamp());
assertEquals(storeTimeStamp, decodeMsgs.get(i).getStoreTimestamp());
assertEquals(queueOffset++, decodeMsgs.get(i).getQueueOffset());
}
}
} }
...@@ -23,6 +23,7 @@ import org.apache.rocketmq.common.message.Message; ...@@ -23,6 +23,7 @@ import org.apache.rocketmq.common.message.Message;
import org.apache.rocketmq.common.message.MessageDecoder; import org.apache.rocketmq.common.message.MessageDecoder;
import org.apache.rocketmq.common.message.MessageExt; import org.apache.rocketmq.common.message.MessageExt;
import org.apache.rocketmq.common.message.MessageExtBatch; import org.apache.rocketmq.common.message.MessageExtBatch;
import org.apache.rocketmq.common.sysflag.MessageSysFlag;
import org.apache.rocketmq.store.config.FlushDiskType; import org.apache.rocketmq.store.config.FlushDiskType;
import org.apache.rocketmq.store.config.MessageStoreConfig; import org.apache.rocketmq.store.config.MessageStoreConfig;
import org.apache.rocketmq.store.stats.BrokerStatsManager; import org.apache.rocketmq.store.stats.BrokerStatsManager;
...@@ -125,6 +126,58 @@ public class BatchPutMessageTest { ...@@ -125,6 +126,58 @@ public class BatchPutMessageTest {
} }
@Test
public void testPutIPv6HostMessages() throws Exception {
List<Message> messages = new ArrayList<>();
String topic = "batch-write-topic";
int queue = 0;
int[] msgLengthArr = new int[11];
msgLengthArr[0] = 0;
int j = 1;
for (int i = 0; i < 10; i++) {
Message msg = new Message();
msg.setBody(("body" + i).getBytes());
msg.setTopic(topic);
msg.setTags("TAG1");
msg.setKeys(String.valueOf(System.currentTimeMillis()));
messages.add(msg);
String properties = messageProperties2String(msg.getProperties());
byte[] propertiesBytes = properties.getBytes(CHARSET_UTF8);
short propertiesLength = (short) propertiesBytes.length;
final byte[] topicData = msg.getTopic().getBytes(MessageDecoder.CHARSET_UTF8);
final int topicLength = topicData.length;
msgLengthArr[j] = calIPv6HostMsgLength(msg.getBody().length, topicLength, propertiesLength) + msgLengthArr[j - 1];
j++;
}
byte[] batchMessageBody = MessageDecoder.encodeMessages(messages);
MessageExtBatch messageExtBatch = new MessageExtBatch();
messageExtBatch.setTopic(topic);
messageExtBatch.setQueueId(queue);
messageExtBatch.setBody(batchMessageBody);
messageExtBatch.setMsgId("24084004018081003FAA1DDE2B3F898A00002A9F0000000000000CA0");
messageExtBatch.setBornTimestamp(System.currentTimeMillis());
messageExtBatch.setSysFlag(0);
messageExtBatch.setBornHostV6Flag();
messageExtBatch.setStoreHostAddressV6Flag();
messageExtBatch.setStoreHost(new InetSocketAddress("1050:0000:0000:0000:0005:0600:300c:326b", 125));
messageExtBatch.setBornHost(new InetSocketAddress("::1", 126));
PutMessageResult putMessageResult = messageStore.putMessages(messageExtBatch);
assertThat(putMessageResult.isOk()).isTrue();
Thread.sleep(3 * 1000);
for (long i = 0; i < 10; i++) {
MessageExt messageExt = messageStore.lookMessageByOffset(msgLengthArr[(int) i]);
assertThat(messageExt).isNotNull();
GetMessageResult result = messageStore.getMessage("batch_write_group", topic, queue, i, 1024 * 1024, null);
assertThat(result).isNotNull();
assertThat(result.getStatus()).isEqualTo(GetMessageStatus.FOUND);
result.release();
}
}
private int calMsgLength(int bodyLength, int topicLength, int propertiesLength) { private int calMsgLength(int bodyLength, int topicLength, int propertiesLength) {
final int msgLen = 4 //TOTALSIZE final int msgLen = 4 //TOTALSIZE
+ 4 //MAGICCODE + 4 //MAGICCODE
...@@ -147,6 +200,28 @@ public class BatchPutMessageTest { ...@@ -147,6 +200,28 @@ public class BatchPutMessageTest {
return msgLen; return msgLen;
} }
private int calIPv6HostMsgLength(int bodyLength, int topicLength, int propertiesLength) {
final int msgLen = 4 //TOTALSIZE
+ 4 //MAGICCODE
+ 4 //BODYCRC
+ 4 //QUEUEID
+ 4 //FLAG
+ 8 //QUEUEOFFSET
+ 8 //PHYSICALOFFSET
+ 4 //SYSFLAG
+ 8 //BORNTIMESTAMP
+ 20 //BORNHOST
+ 8 //STORETIMESTAMP
+ 20 //STOREHOSTADDRESS
+ 4 //RECONSUMETIMES
+ 8 //Prepared Transaction Offset
+ 4 + (bodyLength > 0 ? bodyLength : 0) //BODY
+ 1 + topicLength //TOPIC
+ 2 + (propertiesLength > 0 ? propertiesLength : 0) //propertiesLength
+ 0;
return msgLen;
}
public String messageProperties2String(Map<String, String> properties) { public String messageProperties2String(Map<String, String> properties) {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
if (properties != null) { if (properties != null) {
......
...@@ -83,6 +83,29 @@ public class ConsumeQueueTest { ...@@ -83,6 +83,29 @@ public class ConsumeQueueTest {
return msg; return msg;
} }
public MessageExtBrokerInner buildIPv6HostMessage() {
MessageExtBrokerInner msg = new MessageExtBrokerInner();
msg.setTopic(topic);
msg.setTags("TAG1");
msg.setKeys("Hello");
msg.setBody(msgBody);
msg.setMsgId("24084004018081003FAA1DDE2B3F898A00002A9F0000000000000CA0");
msg.setKeys(String.valueOf(System.currentTimeMillis()));
msg.setQueueId(queueId);
msg.setSysFlag(0);
msg.setBornHostV6Flag();
msg.setStoreHostAddressV6Flag();
msg.setBornTimestamp(System.currentTimeMillis());
msg.setBornHost(new InetSocketAddress("1050:0000:0000:0000:0005:0600:300c:326b", 123));
msg.setStoreHost(new InetSocketAddress("::1", 124));
for (int i = 0; i < 1; i++) {
msg.putUserProperty(String.valueOf(i), "imagoodperson" + i);
}
msg.setPropertiesString(MessageDecoder.messageProperties2String(msg.getProperties()));
return msg;
}
public MessageStoreConfig buildStoreConfig(int commitLogFileSize, int cqFileSize, public MessageStoreConfig buildStoreConfig(int commitLogFileSize, int cqFileSize,
boolean enableCqExt, int cqExtFileSize) { boolean enableCqExt, int cqExtFileSize) {
MessageStoreConfig messageStoreConfig = new MessageStoreConfig(); MessageStoreConfig messageStoreConfig = new MessageStoreConfig();
...@@ -127,7 +150,11 @@ public class ConsumeQueueTest { ...@@ -127,7 +150,11 @@ public class ConsumeQueueTest {
long totalMsgs = 200; long totalMsgs = 200;
for (long i = 0; i < totalMsgs; i++) { for (long i = 0; i < totalMsgs; i++) {
master.putMessage(buildMessage()); if (i < totalMsgs / 2) {
master.putMessage(buildMessage());
} else {
master.putMessage(buildIPv6HostMessage());
}
} }
} }
......
...@@ -24,6 +24,7 @@ import java.lang.reflect.Method; ...@@ -24,6 +24,7 @@ import java.lang.reflect.Method;
import java.net.InetAddress; import java.net.InetAddress;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.net.SocketAddress; import java.net.SocketAddress;
import java.net.UnknownHostException;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.nio.MappedByteBuffer; import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel; import java.nio.channels.FileChannel;
...@@ -116,13 +117,19 @@ public class DefaultMessageStoreTest { ...@@ -116,13 +117,19 @@ public class DefaultMessageStoreTest {
@Test @Test
public void testWriteAndRead() { public void testWriteAndRead() {
long totalMsgs = 10; long ipv4HostMsgs = 10;
long ipv6HostMsgs = 10;
long totalMsgs = ipv4HostMsgs + ipv6HostMsgs;
QUEUE_TOTAL = 1; QUEUE_TOTAL = 1;
MessageBody = StoreMessage.getBytes(); MessageBody = StoreMessage.getBytes();
for (long i = 0; i < totalMsgs; i++) { for (long i = 0; i < ipv4HostMsgs; i++) {
messageStore.putMessage(buildMessage()); messageStore.putMessage(buildMessage());
} }
for (long i = 0; i < ipv6HostMsgs; i++) {
messageStore.putMessage(buildIPv6HostMessage());
}
StoreTestUtil.waitCommitLogReput((DefaultMessageStore) messageStore); StoreTestUtil.waitCommitLogReput((DefaultMessageStore) messageStore);
for (long i = 0; i < totalMsgs; i++) { for (long i = 0; i < totalMsgs; i++) {
...@@ -134,7 +141,7 @@ public class DefaultMessageStoreTest { ...@@ -134,7 +141,7 @@ public class DefaultMessageStoreTest {
} }
@Test @Test
public void should_look_message_successfully_when_offset_is_first() { public void testLookMessageByOffset_OffsetIsFirst() {
final int totalCount = 10; final int totalCount = 10;
int queueId = new Random().nextInt(10); int queueId = new Random().nextInt(10);
String topic = "FooBar"; String topic = "FooBar";
...@@ -150,7 +157,7 @@ public class DefaultMessageStoreTest { ...@@ -150,7 +157,7 @@ public class DefaultMessageStoreTest {
} }
@Test @Test
public void should_look_message_successfully_when_offset_is_last() { public void testLookMessageByOffset_OffsetIsLast() {
final int totalCount = 10; final int totalCount = 10;
int queueId = new Random().nextInt(10); int queueId = new Random().nextInt(10);
String topic = "FooBar"; String topic = "FooBar";
...@@ -164,7 +171,7 @@ public class DefaultMessageStoreTest { ...@@ -164,7 +171,7 @@ public class DefaultMessageStoreTest {
} }
@Test @Test
public void should_look_message_failed_and_return_null_when_offset_is_out_of_bound() { public void testLookMessageByOffset_OffsetIsOutOfBound() {
final int totalCount = 10; final int totalCount = 10;
int queueId = new Random().nextInt(10); int queueId = new Random().nextInt(10);
String topic = "FooBar"; String topic = "FooBar";
...@@ -177,7 +184,7 @@ public class DefaultMessageStoreTest { ...@@ -177,7 +184,7 @@ public class DefaultMessageStoreTest {
} }
@Test @Test
public void should_get_consume_queue_offset_successfully_when_incomming_by_timestamp() throws InterruptedException { public void testGetOffsetInQueueByTime() {
final int totalCount = 10; final int totalCount = 10;
int queueId = 0; int queueId = 0;
String topic = "FooBar"; String topic = "FooBar";
...@@ -196,7 +203,7 @@ public class DefaultMessageStoreTest { ...@@ -196,7 +203,7 @@ public class DefaultMessageStoreTest {
} }
@Test @Test
public void should_get_consume_queue_offset_successfully_when_timestamp_is_skewing() throws InterruptedException { public void testGetOffsetInQueueByTime_TimestampIsSkewing() {
final int totalCount = 10; final int totalCount = 10;
int queueId = 0; int queueId = 0;
String topic = "FooBar"; String topic = "FooBar";
...@@ -221,7 +228,7 @@ public class DefaultMessageStoreTest { ...@@ -221,7 +228,7 @@ public class DefaultMessageStoreTest {
} }
@Test @Test
public void should_get_min_of_max_consume_queue_offset_when_timestamp_s_skewing_is_large() throws InterruptedException { public void testGetOffsetInQueueByTime_TimestampSkewingIsLarge() {
final int totalCount = 10; final int totalCount = 10;
int queueId = 0; int queueId = 0;
String topic = "FooBar"; String topic = "FooBar";
...@@ -247,7 +254,7 @@ public class DefaultMessageStoreTest { ...@@ -247,7 +254,7 @@ public class DefaultMessageStoreTest {
} }
@Test @Test
public void should_return_zero_when_consume_queue_not_found() throws InterruptedException { public void testGetOffsetInQueueByTime_ConsumeQueueNotFound1() {
final int totalCount = 10; final int totalCount = 10;
int queueId = 0; int queueId = 0;
int wrongQueueId = 1; int wrongQueueId = 1;
...@@ -263,7 +270,7 @@ public class DefaultMessageStoreTest { ...@@ -263,7 +270,7 @@ public class DefaultMessageStoreTest {
} }
@Test @Test
public void should_return_negative_one_when_invoke_getMessageStoreTimeStamp_if_consume_queue_not_found() throws InterruptedException { public void testGetOffsetInQueueByTime_ConsumeQueueNotFound2() {
final int totalCount = 10; final int totalCount = 10;
int queueId = 0; int queueId = 0;
int wrongQueueId = 1; int wrongQueueId = 1;
...@@ -278,7 +285,7 @@ public class DefaultMessageStoreTest { ...@@ -278,7 +285,7 @@ public class DefaultMessageStoreTest {
} }
@Test @Test
public void should_return_negative_one_when_invoke_getMessageStoreTimeStamp_if_consumeQueueOffset_not_exist() throws InterruptedException { public void testGetOffsetInQueueByTime_ConsumeQueueOffsetNotExist() {
final int totalCount = 10; final int totalCount = 10;
int queueId = 0; int queueId = 0;
int wrongQueueId = 1; int wrongQueueId = 1;
...@@ -293,9 +300,8 @@ public class DefaultMessageStoreTest { ...@@ -293,9 +300,8 @@ public class DefaultMessageStoreTest {
assertThat(messageStoreTimeStamp).isEqualTo(-1); assertThat(messageStoreTimeStamp).isEqualTo(-1);
} }
@Test @Test
public void should_get_message_store_timestamp_successfully_when_incomming_by_topic_queueId_and_consumeQueueOffset() throws InterruptedException { public void testGetMessageStoreTimeStamp() {
final int totalCount = 10; final int totalCount = 10;
int queueId = 0; int queueId = 0;
String topic = "FooBar"; String topic = "FooBar";
...@@ -304,7 +310,7 @@ public class DefaultMessageStoreTest { ...@@ -304,7 +310,7 @@ public class DefaultMessageStoreTest {
StoreTestUtil.waitCommitLogReput((DefaultMessageStore) messageStore); StoreTestUtil.waitCommitLogReput((DefaultMessageStore) messageStore);
ConsumeQueue consumeQueue = getDefaultMessageStore().findConsumeQueue(topic, queueId); ConsumeQueue consumeQueue = getDefaultMessageStore().findConsumeQueue(topic, queueId);
int minOffsetInQueue = (int)consumeQueue.getMinOffsetInQueue(); int minOffsetInQueue = (int) consumeQueue.getMinOffsetInQueue();
for (int i = minOffsetInQueue; i < consumeQueue.getMaxOffsetInQueue(); i++) { for (int i = minOffsetInQueue; i < consumeQueue.getMaxOffsetInQueue(); i++) {
long messageStoreTimeStamp = messageStore.getMessageStoreTimeStamp(topic, queueId, i); long messageStoreTimeStamp = messageStore.getMessageStoreTimeStamp(topic, queueId, i);
assertThat(messageStoreTimeStamp).isEqualTo(appendMessageResults[i].getStoreTimestamp()); assertThat(messageStoreTimeStamp).isEqualTo(appendMessageResults[i].getStoreTimestamp());
...@@ -312,14 +318,14 @@ public class DefaultMessageStoreTest { ...@@ -312,14 +318,14 @@ public class DefaultMessageStoreTest {
} }
@Test @Test
public void should_return_negative_one_when_invoke_getStoreTime_if_incomming_param_is_null() { public void testGetStoreTime_ParamIsNull() {
long storeTime = getStoreTime(null); long storeTime = getStoreTime(null);
assertThat(storeTime).isEqualTo(-1); assertThat(storeTime).isEqualTo(-1);
} }
@Test @Test
public void should_get_store_time_successfully_when_invoke_getStoreTime_if_everything_is_ok() throws InterruptedException { public void testGetStoreTime_EverythingIsOk() {
final int totalCount = 10; final int totalCount = 10;
int queueId = 0; int queueId = 0;
String topic = "FooBar"; String topic = "FooBar";
...@@ -337,7 +343,7 @@ public class DefaultMessageStoreTest { ...@@ -337,7 +343,7 @@ public class DefaultMessageStoreTest {
} }
@Test @Test
public void should_return_negative_one_when_invoke_getStoreTime_if_phyOffset_is_less_than_commitLog_s_minOffset() { public void testGetStoreTime_PhyOffsetIsLessThanCommitLogMinOffset() {
long phyOffset = -10; long phyOffset = -10;
int size = 138; int size = 138;
ByteBuffer byteBuffer = ByteBuffer.allocate(100); ByteBuffer byteBuffer = ByteBuffer.allocate(100);
...@@ -354,7 +360,7 @@ public class DefaultMessageStoreTest { ...@@ -354,7 +360,7 @@ public class DefaultMessageStoreTest {
} }
private DefaultMessageStore getDefaultMessageStore() { private DefaultMessageStore getDefaultMessageStore() {
return (DefaultMessageStore)this.messageStore; return (DefaultMessageStore) this.messageStore;
} }
private AppendMessageResult[] putMessages(int totalCount, String topic, int queueId) { private AppendMessageResult[] putMessages(int totalCount, String topic, int queueId) {
...@@ -365,7 +371,9 @@ public class DefaultMessageStoreTest { ...@@ -365,7 +371,9 @@ public class DefaultMessageStoreTest {
AppendMessageResult[] appendMessageResultArray = new AppendMessageResult[totalCount]; AppendMessageResult[] appendMessageResultArray = new AppendMessageResult[totalCount];
for (int i = 0; i < totalCount; i++) { for (int i = 0; i < totalCount; i++) {
String messageBody = buildMessageBodyByOffset(StoreMessage, i); String messageBody = buildMessageBodyByOffset(StoreMessage, i);
MessageExtBrokerInner msgInner = buildMessage(messageBody.getBytes(), topic);
MessageExtBrokerInner msgInner =
i < totalCount / 2 ? buildMessage(messageBody.getBytes(), topic) : buildIPv6HostMessage(messageBody.getBytes(), topic);
msgInner.setQueueId(queueId); msgInner.setQueueId(queueId);
PutMessageResult result = messageStore.putMessage(msgInner); PutMessageResult result = messageStore.putMessage(msgInner);
appendMessageResultArray[i] = result.getAppendMessageResult(); appendMessageResultArray[i] = result.getAppendMessageResult();
...@@ -374,7 +382,7 @@ public class DefaultMessageStoreTest { ...@@ -374,7 +382,7 @@ public class DefaultMessageStoreTest {
try { try {
Thread.sleep(10); Thread.sleep(10);
} catch (InterruptedException e) { } catch (InterruptedException e) {
throw new RuntimeException("Thread sleep ERROR"); throw new RuntimeException("Thread sleep ERROR");
} }
} }
} }
...@@ -397,7 +405,7 @@ public class DefaultMessageStoreTest { ...@@ -397,7 +405,7 @@ public class DefaultMessageStoreTest {
try { try {
Method getStoreTime = getDefaultMessageStore().getClass().getDeclaredMethod("getStoreTime", SelectMappedBufferResult.class); Method getStoreTime = getDefaultMessageStore().getClass().getDeclaredMethod("getStoreTime", SelectMappedBufferResult.class);
getStoreTime.setAccessible(true); getStoreTime.setAccessible(true);
return (long)getStoreTime.invoke(getDefaultMessageStore(), result); return (long) getStoreTime.invoke(getDefaultMessageStore(), result);
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) { } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
...@@ -418,10 +426,43 @@ public class DefaultMessageStoreTest { ...@@ -418,10 +426,43 @@ public class DefaultMessageStoreTest {
return msg; return msg;
} }
private MessageExtBrokerInner buildIPv6HostMessage(byte[] messageBody, String topic) {
MessageExtBrokerInner msg = new MessageExtBrokerInner();
msg.setTopic(topic);
msg.setTags("TAG1");
msg.setKeys("Hello");
msg.setBody(messageBody);
msg.setMsgId("24084004018081003FAA1DDE2B3F898A00002A9F0000000000000CA0");
msg.setKeys(String.valueOf(System.currentTimeMillis()));
msg.setQueueId(Math.abs(QueueId.getAndIncrement()) % QUEUE_TOTAL);
msg.setSysFlag(0);
msg.setBornHostV6Flag();
msg.setStoreHostAddressV6Flag();
msg.setBornTimestamp(System.currentTimeMillis());
try {
msg.setBornHost(new InetSocketAddress(InetAddress.getByName("1050:0000:0000:0000:0005:0600:300c:326b"), 0));
} catch (UnknownHostException e) {
e.printStackTrace();
assertThat(Boolean.FALSE).isTrue();
}
try {
msg.setStoreHost(new InetSocketAddress(InetAddress.getByName("::1"), 0));
} catch (UnknownHostException e) {
e.printStackTrace();
assertThat(Boolean.FALSE).isTrue();
}
return msg;
}
private MessageExtBrokerInner buildMessage() { private MessageExtBrokerInner buildMessage() {
return buildMessage(MessageBody, "FooBar"); return buildMessage(MessageBody, "FooBar");
} }
private MessageExtBrokerInner buildIPv6HostMessage() {
return buildIPv6HostMessage(MessageBody, "FooBar");
}
private void verifyThatMasterIsFunctional(long totalMsgs, MessageStore master) { private void verifyThatMasterIsFunctional(long totalMsgs, MessageStore master) {
for (long i = 0; i < totalMsgs; i++) { for (long i = 0; i < totalMsgs; i++) {
master.putMessage(buildMessage()); master.putMessage(buildMessage());
...@@ -477,7 +518,7 @@ public class DefaultMessageStoreTest { ...@@ -477,7 +518,7 @@ public class DefaultMessageStoreTest {
messageStore.putMessage(messageExtBrokerInner); messageStore.putMessage(messageExtBrokerInner);
} }
// Thread.sleep(100);//wait for build consumer queue // Thread.sleep(100);//wait for build consumer queue
StoreTestUtil.waitCommitLogReput((DefaultMessageStore) messageStore); StoreTestUtil.waitCommitLogReput((DefaultMessageStore) messageStore);
long maxPhyOffset = messageStore.getMaxPhyOffset(); long maxPhyOffset = messageStore.getMaxPhyOffset();
...@@ -587,7 +628,7 @@ public class DefaultMessageStoreTest { ...@@ -587,7 +628,7 @@ public class DefaultMessageStoreTest {
private class MyMessageArrivingListener implements MessageArrivingListener { private class MyMessageArrivingListener implements MessageArrivingListener {
@Override @Override
public void arriving(String topic, int queueId, long logicOffset, long tagsCode, long msgStoreTime, public void arriving(String topic, int queueId, long logicOffset, long tagsCode, long msgStoreTime,
byte[] filterBitMap, Map<String, String> properties) { byte[] filterBitMap, Map<String, String> properties) {
} }
} }
} }
...@@ -20,12 +20,12 @@ import java.io.File; ...@@ -20,12 +20,12 @@ import java.io.File;
import java.net.InetAddress; import java.net.InetAddress;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.net.SocketAddress; import java.net.SocketAddress;
import java.net.UnknownHostException;
import java.util.HashSet; import java.util.HashSet;
import java.util.Set; import java.util.Set;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
import org.apache.rocketmq.common.UtilAll; import org.apache.rocketmq.common.UtilAll;
import org.apache.rocketmq.store.config.StorePathConfigHelper;
import org.junit.After; import org.junit.After;
public class StoreTestBase { public class StoreTestBase {
...@@ -59,6 +59,33 @@ public class StoreTestBase { ...@@ -59,6 +59,33 @@ public class StoreTestBase {
return msg; return msg;
} }
protected MessageExtBrokerInner buildIPv6HostMessage() {
MessageExtBrokerInner msg = new MessageExtBrokerInner();
msg.setTopic("StoreTest");
msg.setTags("TAG1");
msg.setKeys("Hello");
msg.setBody(MessageBody);
msg.setMsgId("24084004018081003FAA1DDE2B3F898A00002A9F0000000000000CA0");
msg.setKeys(String.valueOf(System.currentTimeMillis()));
msg.setQueueId(Math.abs(QueueId.getAndIncrement()) % QUEUE_TOTAL);
msg.setSysFlag(0);
msg.setBornHostV6Flag();
msg.setStoreHostAddressV6Flag();
msg.setBornTimestamp(System.currentTimeMillis());
try {
msg.setBornHost(new InetSocketAddress(InetAddress.getByName("1050:0000:0000:0000:0005:0600:300c:326b"), 8123));
} catch (UnknownHostException e) {
e.printStackTrace();
}
try {
msg.setStoreHost(new InetSocketAddress(InetAddress.getByName("::1"), 8123));
} catch (UnknownHostException e) {
e.printStackTrace();
}
return msg;
}
public static String createBaseDir() { public static String createBaseDir() {
String baseDir = System.getProperty("user.home") + File.separator + "unitteststore" + File.separator + UUID.randomUUID(); String baseDir = System.getProperty("user.home") + File.separator + "unitteststore" + File.separator + UUID.randomUUID();
final File file = new File(baseDir); final File file = new File(baseDir);
...@@ -74,7 +101,6 @@ public class StoreTestBase { ...@@ -74,7 +101,6 @@ public class StoreTestBase {
return file.createNewFile(); return file.createNewFile();
} }
public static void deleteFile(String fileName) { public static void deleteFile(String fileName) {
deleteFile(new File(fileName)); deleteFile(new File(fileName));
} }
......
...@@ -145,7 +145,8 @@ public class DLedgerCommitlogTest extends MessageStoreTestBase { ...@@ -145,7 +145,8 @@ public class DLedgerCommitlogTest extends MessageStoreTestBase {
List<PutMessageResult> results = new ArrayList<>(); List<PutMessageResult> results = new ArrayList<>();
for (int i = 0; i < 10; i++) { for (int i = 0; i < 10; i++) {
MessageExtBrokerInner msgInner = buildMessage(); MessageExtBrokerInner msgInner =
i < 5 ? buildMessage() : buildIPv6HostMessage();
msgInner.setTopic(topic); msgInner.setTopic(topic);
msgInner.setQueueId(0); msgInner.setQueueId(0);
PutMessageResult putMessageResult = messageStore.putMessage(msgInner); PutMessageResult putMessageResult = messageStore.putMessage(msgInner);
...@@ -209,5 +210,39 @@ public class DLedgerCommitlogTest extends MessageStoreTestBase { ...@@ -209,5 +210,39 @@ public class DLedgerCommitlogTest extends MessageStoreTestBase {
followerStore.shutdown(); followerStore.shutdown();
} }
@Test
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);
String topic = UUID.randomUUID().toString();
MessageExtBrokerInner msgInner = buildIPv6HostMessage();
msgInner.setTopic(topic);
msgInner.setQueueId(0);
PutMessageResult putMessageResult = leaderStore.putMessage(msgInner);
Assert.assertEquals(PutMessageStatus.OS_PAGECACHE_BUSY, putMessageResult.getPutMessageStatus());
Thread.sleep(1000);
Assert.assertEquals(0, leaderStore.getCommitLog().getMaxOffset());
Assert.assertEquals(0, leaderStore.getMaxOffsetInQueue(topic, 0));
DefaultMessageStore followerStore = createDledgerMessageStore(createBaseDir(), group,"n1", peers, "n0", false, 0);
Thread.sleep(2000);
Assert.assertEquals(1, leaderStore.getMaxOffsetInQueue(topic, 0));
Assert.assertEquals(1, followerStore.getMaxOffsetInQueue(topic, 0));
Assert.assertTrue(leaderStore.getCommitLog().getMaxOffset() > 0);
leaderStore.destroy();
followerStore.destroy();
leaderStore.shutdown();
followerStore.shutdown();
}
} }
...@@ -19,6 +19,7 @@ package org.apache.rocketmq.store.dledger; ...@@ -19,6 +19,7 @@ package org.apache.rocketmq.store.dledger;
import io.openmessaging.storage.dledger.DLedgerConfig; import io.openmessaging.storage.dledger.DLedgerConfig;
import io.openmessaging.storage.dledger.DLedgerServer; import io.openmessaging.storage.dledger.DLedgerServer;
import java.io.File; import java.io.File;
import java.net.UnknownHostException;
import java.util.Arrays; import java.util.Arrays;
import org.apache.rocketmq.common.BrokerConfig; import org.apache.rocketmq.common.BrokerConfig;
import org.apache.rocketmq.common.message.MessageDecoder; import org.apache.rocketmq.common.message.MessageDecoder;
...@@ -118,7 +119,7 @@ public class MessageStoreTestBase extends StoreTestBase { ...@@ -118,7 +119,7 @@ public class MessageStoreTestBase extends StoreTestBase {
return defaultMessageStore; return defaultMessageStore;
} }
protected void doPutMessages(MessageStore messageStore, String topic, int queueId, int num, long beginLogicsOffset) { protected void doPutMessages(MessageStore messageStore, String topic, int queueId, int num, long beginLogicsOffset) throws UnknownHostException {
for (int i = 0; i < num; i++) { for (int i = 0; i < num; i++) {
MessageExtBrokerInner msgInner = buildMessage(); MessageExtBrokerInner msgInner = buildMessage();
msgInner.setTopic(topic); msgInner.setTopic(topic);
......
...@@ -25,6 +25,7 @@ import org.apache.rocketmq.client.ClientConfig; ...@@ -25,6 +25,7 @@ import org.apache.rocketmq.client.ClientConfig;
import org.apache.rocketmq.client.QueryResult; import org.apache.rocketmq.client.QueryResult;
import org.apache.rocketmq.client.exception.MQBrokerException; import org.apache.rocketmq.client.exception.MQBrokerException;
import org.apache.rocketmq.client.exception.MQClientException; import org.apache.rocketmq.client.exception.MQClientException;
import org.apache.rocketmq.common.AclConfig;
import org.apache.rocketmq.common.MixAll; import org.apache.rocketmq.common.MixAll;
import org.apache.rocketmq.common.PlainAccessConfig; import org.apache.rocketmq.common.PlainAccessConfig;
import org.apache.rocketmq.common.TopicConfig; import org.apache.rocketmq.common.TopicConfig;
...@@ -183,6 +184,11 @@ public class DefaultMQAdminExt extends ClientConfig implements MQAdminExt { ...@@ -183,6 +184,11 @@ public class DefaultMQAdminExt extends ClientConfig implements MQAdminExt {
return defaultMQAdminExtImpl.examineBrokerClusterAclVersionInfo(addr); return defaultMQAdminExtImpl.examineBrokerClusterAclVersionInfo(addr);
} }
@Override public AclConfig examineBrokerClusterAclConfig(
String addr) throws RemotingException, MQBrokerException, InterruptedException, MQClientException {
return defaultMQAdminExtImpl.examineBrokerClusterAclConfig(addr);
}
@Override @Override
public void createAndUpdateSubscriptionGroupConfig(String addr, public void createAndUpdateSubscriptionGroupConfig(String addr,
SubscriptionGroupConfig config) throws RemotingException, SubscriptionGroupConfig config) throws RemotingException,
......
...@@ -41,6 +41,7 @@ import org.apache.rocketmq.common.MixAll; ...@@ -41,6 +41,7 @@ import org.apache.rocketmq.common.MixAll;
import org.apache.rocketmq.common.PlainAccessConfig; import org.apache.rocketmq.common.PlainAccessConfig;
import org.apache.rocketmq.common.ServiceState; import org.apache.rocketmq.common.ServiceState;
import org.apache.rocketmq.common.TopicConfig; import org.apache.rocketmq.common.TopicConfig;
import org.apache.rocketmq.common.AclConfig;
import org.apache.rocketmq.common.UtilAll; import org.apache.rocketmq.common.UtilAll;
import org.apache.rocketmq.common.admin.ConsumeStats; import org.apache.rocketmq.common.admin.ConsumeStats;
import org.apache.rocketmq.common.admin.OffsetWrapper; import org.apache.rocketmq.common.admin.OffsetWrapper;
...@@ -202,6 +203,12 @@ public class DefaultMQAdminExtImpl implements MQAdminExt, MQAdminExtInner { ...@@ -202,6 +203,12 @@ public class DefaultMQAdminExtImpl implements MQAdminExt, MQAdminExtInner {
return this.mqClientInstance.getMQClientAPIImpl().getBrokerClusterAclInfo(addr, timeoutMillis); return this.mqClientInstance.getMQClientAPIImpl().getBrokerClusterAclInfo(addr, timeoutMillis);
} }
@Override
public AclConfig examineBrokerClusterAclConfig(
String addr) throws RemotingException, MQBrokerException, InterruptedException, MQClientException {
return this.mqClientInstance.getMQClientAPIImpl().getBrokerClusterConfig(addr, timeoutMillis);
}
@Override @Override
public void createAndUpdateSubscriptionGroupConfig(String addr, public void createAndUpdateSubscriptionGroupConfig(String addr,
SubscriptionGroupConfig config) throws RemotingException, SubscriptionGroupConfig config) throws RemotingException,
......
...@@ -24,6 +24,7 @@ import java.util.Set; ...@@ -24,6 +24,7 @@ import java.util.Set;
import org.apache.rocketmq.client.MQAdmin; import org.apache.rocketmq.client.MQAdmin;
import org.apache.rocketmq.client.exception.MQBrokerException; import org.apache.rocketmq.client.exception.MQBrokerException;
import org.apache.rocketmq.client.exception.MQClientException; import org.apache.rocketmq.client.exception.MQClientException;
import org.apache.rocketmq.common.AclConfig;
import org.apache.rocketmq.common.PlainAccessConfig; import org.apache.rocketmq.common.PlainAccessConfig;
import org.apache.rocketmq.common.TopicConfig; import org.apache.rocketmq.common.TopicConfig;
import org.apache.rocketmq.common.admin.ConsumeStats; import org.apache.rocketmq.common.admin.ConsumeStats;
...@@ -82,6 +83,9 @@ public interface MQAdminExt extends MQAdmin { ...@@ -82,6 +83,9 @@ public interface MQAdminExt extends MQAdmin {
ClusterAclVersionInfo examineBrokerClusterAclVersionInfo(final String addr) throws RemotingException, MQBrokerException, ClusterAclVersionInfo examineBrokerClusterAclVersionInfo(final String addr) throws RemotingException, MQBrokerException,
InterruptedException, MQClientException; InterruptedException, MQClientException;
AclConfig examineBrokerClusterAclConfig(final String addr) throws RemotingException, MQBrokerException,
InterruptedException, MQClientException;
void createAndUpdateSubscriptionGroupConfig(final String addr, void createAndUpdateSubscriptionGroupConfig(final String addr,
final SubscriptionGroupConfig config) throws RemotingException, final SubscriptionGroupConfig config) throws RemotingException,
MQBrokerException, InterruptedException, MQClientException; MQBrokerException, InterruptedException, MQClientException;
......
...@@ -31,6 +31,7 @@ import org.apache.rocketmq.remoting.RPCHook; ...@@ -31,6 +31,7 @@ import org.apache.rocketmq.remoting.RPCHook;
import org.apache.rocketmq.remoting.protocol.RemotingCommand; import org.apache.rocketmq.remoting.protocol.RemotingCommand;
import org.apache.rocketmq.srvutil.ServerUtil; import org.apache.rocketmq.srvutil.ServerUtil;
import org.apache.rocketmq.tools.command.acl.ClusterAclConfigVersionListSubCommand; import org.apache.rocketmq.tools.command.acl.ClusterAclConfigVersionListSubCommand;
import org.apache.rocketmq.tools.command.acl.GetAccessConfigSubCommand;
import org.apache.rocketmq.tools.command.acl.DeleteAccessConfigSubCommand; import org.apache.rocketmq.tools.command.acl.DeleteAccessConfigSubCommand;
import org.apache.rocketmq.tools.command.acl.UpdateAccessConfigSubCommand; import org.apache.rocketmq.tools.command.acl.UpdateAccessConfigSubCommand;
import org.apache.rocketmq.tools.command.acl.UpdateGlobalWhiteAddrSubCommand; import org.apache.rocketmq.tools.command.acl.UpdateGlobalWhiteAddrSubCommand;
...@@ -209,6 +210,7 @@ public class MQAdminStartup { ...@@ -209,6 +210,7 @@ public class MQAdminStartup {
initCommand(new DeleteAccessConfigSubCommand()); initCommand(new DeleteAccessConfigSubCommand());
initCommand(new ClusterAclConfigVersionListSubCommand()); initCommand(new ClusterAclConfigVersionListSubCommand());
initCommand(new UpdateGlobalWhiteAddrSubCommand()); initCommand(new UpdateGlobalWhiteAddrSubCommand());
initCommand(new GetAccessConfigSubCommand());
} }
private static void initLogback() throws JoranException { private static void initLogback() throws JoranException {
......
/*
* 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.acl;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.Option;
import org.apache.commons.cli.OptionGroup;
import org.apache.commons.cli.Options;
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.PlainAccessConfig;
import org.apache.rocketmq.remoting.RPCHook;
import org.apache.rocketmq.remoting.exception.RemotingException;
import org.apache.rocketmq.srvutil.ServerUtil;
import org.apache.rocketmq.tools.admin.DefaultMQAdminExt;
import org.apache.rocketmq.tools.command.CommandUtil;
import org.apache.rocketmq.tools.command.SubCommand;
import org.apache.rocketmq.tools.command.SubCommandException;
import java.lang.reflect.Field;
import java.util.List;
import java.util.Set;
public class GetAccessConfigSubCommand implements SubCommand {
@Override public String commandName() {
return "getAccessConfigSubCommand";
}
@Override public String commandDesc() {
return "List all of acl config information in cluster";
}
@Override public Options buildCommandlineOptions(Options options) {
OptionGroup optionGroup = new OptionGroup();
Option opt = new Option("b", "brokerAddr", true, "query acl config version for which broker");
optionGroup.addOption(opt);
opt = new Option("c", "clusterName", true, "query acl config version for specified cluster");
optionGroup.addOption(opt);
optionGroup.setRequired(true);
options.addOptionGroup(optionGroup);
return options;
}
@Override public void execute(CommandLine commandLine, Options options,
RPCHook rpcHook) throws SubCommandException {
DefaultMQAdminExt defaultMQAdminExt = new DefaultMQAdminExt(rpcHook);
defaultMQAdminExt.setInstanceName(Long.toString(System.currentTimeMillis()));
try {
if (commandLine.hasOption('b')) {
String addr = commandLine.getOptionValue('b').trim();
defaultMQAdminExt.start();
printClusterBaseInfo(defaultMQAdminExt, addr);
return;
} else if (commandLine.hasOption('c')) {
String clusterName = commandLine.getOptionValue('c').trim();
defaultMQAdminExt.start();
Set<String> masterSet =
CommandUtil.fetchMasterAddrByClusterName(defaultMQAdminExt, clusterName);
for (String addr : masterSet) {
printClusterBaseInfo(defaultMQAdminExt, addr);
}
return;
}
ServerUtil.printCommandLineHelp("mqadmin " + this.commandName(), options);
} catch (Exception e) {
throw new SubCommandException(this.getClass().getSimpleName() + " command failed", e);
} finally {
defaultMQAdminExt.shutdown();
}
}
private void printClusterBaseInfo(
final DefaultMQAdminExt defaultMQAdminExt, final String addr) throws
InterruptedException, MQBrokerException, RemotingException, MQClientException, IllegalAccessException {
AclConfig aclConfig = defaultMQAdminExt.examineBrokerClusterAclConfig(addr);
List<PlainAccessConfig> configs = aclConfig.getPlainAccessConfigs();
List<String> globalWhiteAddrs = aclConfig.getGlobalWhiteAddrs();
System.out.printf("\n");
System.out.printf("%-20s: %s\n", "globalWhiteRemoteAddresses", globalWhiteAddrs.toString());
System.out.printf("\n");
System.out.printf("accounts:\n");
if (configs != null && configs.size() > 0) {
for (PlainAccessConfig config : configs) {
Field[] fields = config.getClass().getDeclaredFields();
for (Field field : fields) {
field.setAccessible(true);
if (field.get(config) != null) {
System.out.printf("%-1s %-18s: %s\n", "", field.getName(), field.get(config).toString());
} else {
System.out.printf("%-1s %-18s: %s\n", "", field.getName(), "");
}
}
System.out.printf("\n");
}
}
}
}
...@@ -66,11 +66,6 @@ public class QueryMsgByIdSubCommand implements SubCommand { ...@@ -66,11 +66,6 @@ public class QueryMsgByIdSubCommand implements SubCommand {
msgId msgId
); );
System.out.printf("%-20s %s%n",
"OffsetID:",
msgId
);
System.out.printf("%-20s %s%n", System.out.printf("%-20s %s%n",
"Topic:", "Topic:",
msg.getTopic() msg.getTopic()
......
...@@ -16,12 +16,16 @@ ...@@ -16,12 +16,16 @@
*/ */
package org.apache.rocketmq.tools.command.topic; package org.apache.rocketmq.tools.command.topic;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Set; import java.util.Set;
import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.Option; import org.apache.commons.cli.Option;
import org.apache.commons.cli.Options; import org.apache.commons.cli.Options;
import org.apache.rocketmq.common.MixAll;
import org.apache.rocketmq.common.TopicConfig; import org.apache.rocketmq.common.TopicConfig;
import org.apache.rocketmq.common.protocol.route.BrokerData;
import org.apache.rocketmq.common.protocol.route.QueueData; import org.apache.rocketmq.common.protocol.route.QueueData;
import org.apache.rocketmq.common.protocol.route.TopicRouteData; import org.apache.rocketmq.common.protocol.route.TopicRouteData;
import org.apache.rocketmq.remoting.RPCHook; import org.apache.rocketmq.remoting.RPCHook;
...@@ -67,46 +71,89 @@ public class UpdateTopicPermSubCommand implements SubCommand { ...@@ -67,46 +71,89 @@ public class UpdateTopicPermSubCommand implements SubCommand {
@Override @Override
public void execute(final CommandLine commandLine, final Options options, public void execute(final CommandLine commandLine, final Options options,
RPCHook rpcHook) throws SubCommandException { RPCHook rpcHook) throws SubCommandException {
DefaultMQAdminExt defaultMQAdminExt = new DefaultMQAdminExt(rpcHook); DefaultMQAdminExt defaultMQAdminExt = new DefaultMQAdminExt(rpcHook);
defaultMQAdminExt.setInstanceName(Long.toString(System.currentTimeMillis())); defaultMQAdminExt.setInstanceName(Long.toString(System.currentTimeMillis()));
try { try {
defaultMQAdminExt.start(); defaultMQAdminExt.start();
TopicConfig topicConfig = new TopicConfig();
String topic = commandLine.getOptionValue('t').trim(); TopicConfig topicConfig = new TopicConfig();
String topic;
if (commandLine.hasOption('t')) {
topic = commandLine.getOptionValue('t').trim();
} else {
System.out.printf("topic paramter value must be need.%n");
return;
}
TopicRouteData topicRouteData = defaultMQAdminExt.examineTopicRouteInfo(topic); TopicRouteData topicRouteData = defaultMQAdminExt.examineTopicRouteInfo(topic);
assert topicRouteData != null; assert topicRouteData != null;
List<QueueData> queueDatas = topicRouteData.getQueueDatas(); List<QueueData> queueDatas = topicRouteData.getQueueDatas();
assert queueDatas != null && queueDatas.size() > 0; assert queueDatas != null && queueDatas.size() > 0;
QueueData queueData = queueDatas.get(0); QueueData queueData = queueDatas.get(0);
topicConfig.setTopicName(topic); topicConfig.setTopicName(topic);
topicConfig.setWriteQueueNums(queueData.getWriteQueueNums()); topicConfig.setWriteQueueNums(queueData.getWriteQueueNums());
topicConfig.setReadQueueNums(queueData.getReadQueueNums()); topicConfig.setReadQueueNums(queueData.getReadQueueNums());
topicConfig.setPerm(queueData.getPerm());
topicConfig.setTopicSysFlag(queueData.getTopicSynFlag()); topicConfig.setTopicSysFlag(queueData.getTopicSynFlag());
//new perm //new perm
int perm = Integer.parseInt(commandLine.getOptionValue('p').trim()); int perm;
int oldPerm = topicConfig.getPerm(); if (commandLine.hasOption('p')) {
if (perm == oldPerm) { perm = Integer.parseInt(commandLine.getOptionValue('p').trim());
System.out.printf("new perm equals to the old one!%n"); } else {
System.out.printf("perm paramter value must be need.%n");
return; return;
} }
topicConfig.setPerm(perm); topicConfig.setPerm(perm);
if (commandLine.hasOption('b')) { if (commandLine.hasOption('b')) {
String addr = commandLine.getOptionValue('b').trim(); String brokerAddr = commandLine.getOptionValue('b').trim();
defaultMQAdminExt.createAndUpdateTopicConfig(addr, topicConfig); List<BrokerData> brokerDatas = topicRouteData.getBrokerDatas();
System.out.printf("update topic perm from %s to %s in %s success.%n", oldPerm, perm, addr); String brokerName = null;
System.out.printf("%s%n", topicConfig); for (BrokerData data : brokerDatas) {
return; HashMap<Long, String> brokerAddrs = data.getBrokerAddrs();
if (brokerAddrs == null || brokerAddrs.size() == 0) {
continue;
}
for (Map.Entry<Long, String> entry : brokerAddrs.entrySet()) {
if (brokerAddr.equals(entry.getValue()) && MixAll.MASTER_ID == entry.getKey()) {
brokerName = data.getBrokerName();
break;
}
}
if (brokerName != null) {
break;
}
}
if (brokerName != null) {
List<QueueData> queueDataList = topicRouteData.getQueueDatas();
assert queueDataList != null && queueDataList.size() > 0;
int oldPerm = 0;
for (QueueData data : queueDataList) {
if (brokerName.equals(data.getBrokerName())) {
oldPerm = data.getPerm();
if (perm == oldPerm) {
System.out.printf("new perm equals to the old one!%n");
return;
}
break;
}
}
defaultMQAdminExt.createAndUpdateTopicConfig(brokerAddr, topicConfig);
System.out.printf("update topic perm from %s to %s in %s success.%n", oldPerm, perm, brokerAddr);
System.out.printf("%s.%n", topicConfig);
return;
} else {
System.out.printf("updateTopicPerm error broker not exit or broker is not master!.%n");
return;
}
} else if (commandLine.hasOption('c')) { } else if (commandLine.hasOption('c')) {
String clusterName = commandLine.getOptionValue('c').trim(); String clusterName = commandLine.getOptionValue('c').trim();
Set<String> masterSet = Set<String> masterSet =
CommandUtil.fetchMasterAddrByClusterName(defaultMQAdminExt, clusterName); CommandUtil.fetchMasterAddrByClusterName(defaultMQAdminExt, clusterName);
for (String addr : masterSet) { for (String addr : masterSet) {
defaultMQAdminExt.createAndUpdateTopicConfig(addr, topicConfig); defaultMQAdminExt.createAndUpdateTopicConfig(addr, topicConfig);
System.out.printf("update topic perm from %s to %s in %s success.%n", oldPerm, perm, addr); System.out.printf("update topic perm from %s to %s in %s success.%n", queueData.getPerm(), perm, addr);
} }
return; return;
} }
......
/*
* 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.acl;
import org.apache.commons.cli.*;
import org.apache.rocketmq.srvutil.ServerUtil;
import org.junit.Test;
import static org.assertj.core.api.Assertions.assertThat;
public class GetAccessConfigSubCommandTest {
@Test
public void testExecute() {
GetAccessConfigSubCommand cmd = new GetAccessConfigSubCommand();
Options options = ServerUtil.buildCommandlineOptions(new Options());
String[] subargs = new String[] {"-c default-cluster"};
final CommandLine commandLine =
ServerUtil.parseCmdLine("mqadmin " + cmd.commandName(), subargs, cmd.buildCommandlineOptions(options), new PosixParser());
assertThat(commandLine.getOptionValue('c').trim()).isEqualTo("default-cluster");
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册