/** * $Id: RemotingHelper.java 1831 2013-05-16 01:39:51Z shijia.wxr $ */ package com.alibaba.rocketmq.remoting.common; import io.netty.channel.Channel; import java.io.IOException; import java.net.InetSocketAddress; import java.net.SocketAddress; import java.nio.ByteBuffer; import java.nio.channels.SocketChannel; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map.Entry; import java.util.Properties; import java.util.Set; import com.google.protobuf.InvalidProtocolBufferException; import com.alibaba.rocketmq.remoting.exception.RemotingConnectException; import com.alibaba.rocketmq.remoting.exception.RemotingSendRequestException; import com.alibaba.rocketmq.remoting.exception.RemotingTimeoutException; import com.alibaba.rocketmq.remoting.protocol.RemotingCommand; import com.alibaba.rocketmq.remoting.protocol.RemotingProtos.KVPair; import com.alibaba.rocketmq.remoting.protocol.RemotingProtos.KVPairList; import com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPair; import com.alibaba.rocketmq.remoting.protocol.RemotingProtos.NVPairList; import com.alibaba.rocketmq.remoting.protocol.RemotingProtos.StringList; /** * @author vintage.wang@gmail.com shijia.wxr@taobao.com * */ public class RemotingHelper { public static final String RemotingLogName = "RocketmqRemoting"; /** * IP:PORT */ public static SocketAddress string2SocketAddress(final String addr) { String[] s = addr.split(":"); InetSocketAddress isa = new InetSocketAddress(s[0], Integer.valueOf(s[1])); return isa; } /** * ���л��ַ����б� */ public static byte[] stringList2Bytes(final List<String> strs) { if (null == strs || strs.isEmpty()) { return null; } StringList.Builder builder = StringList.newBuilder(); for (String str : strs) { builder.addName(str); } return builder.build().toByteArray(); } /** * �����л��ַ����б� */ public static List<String> bytes2StringList(final byte[] data) throws InvalidProtocolBufferException { if (null == data) { return null; } StringList stringList = StringList.parseFrom(data); return stringList.getNameList(); } /** * ���л���ֵ�� */ public static byte[] hashMap2Bytes(final HashMap<Integer/* key */, String/* value */> nms) { if (null == nms || nms.isEmpty()) { return null; } KVPairList.Builder builder = KVPairList.newBuilder(); Iterator<Entry<Integer, String>> it = nms.entrySet().iterator(); for (int index = 0; it.hasNext(); index++) { Entry<Integer, String> entry = (Entry<Integer, String>) it.next(); int key = entry.getKey(); String val = entry.getValue(); KVPair.Builder kvb = KVPair.newBuilder(); kvb.setKey(key); kvb.setValue(val); builder.addFields(index, kvb.build()); } return builder.build().toByteArray(); } /** * �����л���ֵ�� * * @throws InvalidProtocolBufferException */ public static HashMap<Integer/* key */, String/* value */> bytes2HashMap(final byte[] data) throws InvalidProtocolBufferException { if (null == data) { return null; } HashMap<Integer/* key */, String/* value */> result = new HashMap<Integer/* key */, String/* value */>(); KVPairList kvList = KVPairList.parseFrom(data); List<KVPair> kvList2 = kvList.getFieldsList(); for (KVPair kv : kvList2) { result.put(kv.getKey(), kv.getValue()); } return result; } /** * ���л���ֵ�� */ public static byte[] hashMapString2Bytes(final HashMap<String/* name */, String/* value */> nms) { if (null == nms || nms.isEmpty()) { return null; } NVPairList.Builder builder = NVPairList.newBuilder(); Iterator<Entry<String, String>> it = nms.entrySet().iterator(); for (int index = 0; it.hasNext(); index++) { Entry<String, String> entry = (Entry<String, String>) it.next(); String key = entry.getKey(); String val = entry.getValue(); NVPair.Builder kvb = NVPair.newBuilder(); kvb.setName(key); kvb.setValue(val); builder.addFields(index, kvb.build()); } return builder.build().toByteArray(); } /** * ���л���ֵ�� */ public static byte[] properties2Bytes(final Properties nms) { if (null == nms || nms.isEmpty()) { return null; } NVPairList.Builder builder = NVPairList.newBuilder(); Set<Object> keyset = nms.keySet(); int index = 0; for (Object object : keyset) { String key = object.toString(); String val = nms.getProperty(key); NVPair.Builder kvb = NVPair.newBuilder(); kvb.setName(key); kvb.setValue(val); builder.addFields(index++, kvb.build()); } return builder.build().toByteArray(); } /** * �����л���ֵ�� * * @throws InvalidProtocolBufferException */ public static HashMap<String/* name */, String/* value */> bytes2HashMapString(final byte[] data) throws InvalidProtocolBufferException { if (null == data) { return null; } HashMap<String/* name */, String/* value */> result = new HashMap<String/* name */, String/* value */>(); NVPairList ps = NVPairList.parseFrom(data); List<NVPair> ps2 = ps.getFieldsList(); for (NVPair kv : ps2) { result.put(kv.getName(), kv.getValue()); } return result; } /** * �����ӵ��� TODO */ public static RemotingCommand invokeSync(final String addr, final RemotingCommand request, final long timeoutMillis) throws InterruptedException, RemotingConnectException, RemotingSendRequestException, RemotingTimeoutException { long beginTime = System.currentTimeMillis(); SocketAddress socketAddress = RemotingUtil.string2SocketAddress(addr); SocketChannel socketChannel = RemotingUtil.connect(socketAddress); if (socketChannel != null) { boolean sendRequestOK = false; try { // ʹ������ģʽ socketChannel.configureBlocking(true); /* * FIXME The read methods in SocketChannel (and DatagramChannel) * do notsupport timeouts * http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4614802 */ socketChannel.socket().setSoTimeout((int) timeoutMillis); // �������� ByteBuffer byteBufferRequest = request.encode(); while (byteBufferRequest.hasRemaining()) { int length = socketChannel.write(byteBufferRequest); if (length > 0) { if (byteBufferRequest.hasRemaining()) { if ((System.currentTimeMillis() - beginTime) > timeoutMillis) { // ��������ʱ throw new RemotingSendRequestException(addr); } } } else { throw new RemotingSendRequestException(addr); } // �Ƚ��� Thread.sleep(1); } sendRequestOK = true; // ����Ӧ�� SIZE ByteBuffer byteBufferSize = ByteBuffer.allocate(4); while (byteBufferSize.hasRemaining()) { int length = socketChannel.read(byteBufferSize); if (length > 0) { if (byteBufferSize.hasRemaining()) { if ((System.currentTimeMillis() - beginTime) > timeoutMillis) { // ����Ӧ��ʱ throw new RemotingTimeoutException(addr, timeoutMillis); } } } else { throw new RemotingTimeoutException(addr, timeoutMillis); } // �Ƚ��� Thread.sleep(1); } // ����Ӧ�� BODY int size = byteBufferSize.getInt(0); ByteBuffer byteBufferBody = ByteBuffer.allocate(size); while (byteBufferBody.hasRemaining()) { int length = socketChannel.read(byteBufferBody); if (length > 0) { if (byteBufferBody.hasRemaining()) { if ((System.currentTimeMillis() - beginTime) > timeoutMillis) { // ����Ӧ��ʱ throw new RemotingTimeoutException(addr, timeoutMillis); } } } else { throw new RemotingTimeoutException(addr, timeoutMillis); } // �Ƚ��� Thread.sleep(1); } // ��Ӧ�����ݽ��� byteBufferBody.flip(); return RemotingCommand.decode(byteBufferBody); } catch (IOException e) { e.printStackTrace(); if (sendRequestOK) { throw new RemotingTimeoutException(addr, timeoutMillis); } else { throw new RemotingSendRequestException(addr); } } finally { try { socketChannel.close(); } catch (IOException e) { e.printStackTrace(); } } } else { throw new RemotingConnectException(addr); } } public static String parseChannelRemoteAddr(final Channel channel) { final SocketAddress remote = channel.remoteAddress(); final String addr = remote != null ? remote.toString() : ""; if (addr.length() > 0) { return addr.substring(1); } return ""; } }