package com.alipay.bluewhale.core.zilch; import java.nio.ByteBuffer; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import org.apache.log4j.Logger; import org.zeromq.ZMQ; import org.zeromq.ZMQ.Context; import org.zeromq.ZMQ.Socket; import backtype.storm.daemon.Shutdownable; import com.alipay.bluewhale.core.callback.RunnableCallback; import com.alipay.bluewhale.core.utils.AsyncLoopThread; /** * zeromq ����˿ڵ�ʵ�֣�����worker������Ϣ��Ȼ���򱾵�task�ַ���Ϣ����߼��� ������ᴴ��һ���̣߳����ϵĽ�����Ϣ���ַ� * * @author yannian * */ public class VirtualPort { private static Logger LOG = Logger.getLogger(VirtualPort.class); public static byte[] mk_packet(Integer virtual_port, byte[] message) { ByteBuffer buff = ByteBuffer.allocate((Integer.SIZE / 8) + message.length); buff.putInt(virtual_port); buff.put(message); byte[] rtn = buff.array(); return rtn; } public static PacketPair parse_packet(byte[] packet) { ByteBuffer buff = ByteBuffer.wrap(packet); Integer port = buff.getInt(); byte[] message = new byte[buff.array().length - (Integer.SIZE / 8)]; buff.get(message); PacketPair pair = new PacketPair(port,message); return pair; } public static String virtual_url(int port) { return "inproc://" + port; } public static Socket get_virtual_socket(Context context, Map<Integer, Socket> mapping_atom, Integer port, String debugurl) { synchronized (mapping_atom) { if (!mapping_atom.containsKey(port)) { for(int i=0;i<62;i++) { try { LOG.info("Connecting to virtual port " + port + ",bind=" + debugurl); Socket socket = ZeroMq.socket(context, ZeroMq.push); String vurl = virtual_url(port); socket = ZeroMq.connect(socket, vurl); mapping_atom.put(port, socket); break; } catch (org.zeromq.ZMQException e) { LOG.info("Connecting error "+i,e); if(i>=60) { throw e; } try { Thread.sleep(1000l*10); } catch (InterruptedException e1) { } } } } return mapping_atom.get(port); } } public static Socket get_virtual_socket(Context context, Map<Integer, Socket> mapping_atom, Integer port) { return get_virtual_socket(context, mapping_atom, port, ""); } public static void close_virtual_sockets(Map<Integer, Socket> mapping_atom) { synchronized (mapping_atom) { for (Entry<Integer, Socket> entry : mapping_atom.entrySet()) { entry.getValue().close(); } mapping_atom.clear(); } } public static Socket virtual_send(Socket socket, Integer virtual_port, byte[] message, int flags) { return ZeroMq.send(socket, mk_packet(virtual_port, message), flags); } public static Socket virtual_send(Socket socket, int virtual_port, byte[] message) { return virtual_send(socket, virtual_port, message, ZMQ.NOBLOCK); } public static Shutdownable launch_virtual_port(Context context, String url, boolean daemon, RunnableCallback kill_fn, Integer priority, Integer[] valid_ports) { HashSet<Integer> sets = new HashSet<Integer>(); for (Integer i : valid_ports) { sets.add(i); } return launch_virtual_port(context, url, daemon, kill_fn, priority, sets); } public static Shutdownable launch_virtual_port(Context context, String url, boolean daemon, RunnableCallback kill_fn, Integer priority, Set<Integer> valid_ports) { Socket socket = ZeroMq.socket(context, ZeroMq.pull); for(int i=0;i<605;i++) { try{ ZeroMq.bind(socket, url); LOG.info("bind:"+url); break; }catch(org.zeromq.ZMQException e) { LOG.info("zeromqBind error"+i,e); if(i>=600) { throw e; } try { Thread.sleep(1000l*3); } catch (InterruptedException e1) { } } } Map<Integer, Socket> virtual_mapping = new HashMap<Integer, ZMQ.Socket>(); RunnableCallback loop_fn = new VirtualPortDispatch(context, socket, virtual_mapping, url, valid_ports); AsyncLoopThread vthread = new AsyncLoopThread(loop_fn, daemon, kill_fn, priority, true); return new VirtualPortShutdown(context, vthread, url); } public static Socket virtual_bind(Socket socket, int virtual_port) { return ZeroMq.bind(socket, virtual_url(virtual_port)); } public static Socket virtual_connect(Socket socket, Integer virtual_port) { return ZeroMq.connect(socket, virtual_url(virtual_port)); } }