package org.zbus.server.mq; import java.io.IOException; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.concurrent.BlockingQueue; import java.util.concurrent.ExecutorService; import java.util.concurrent.LinkedBlockingQueue; import org.zbus.common.logging.Logger; import org.zbus.common.logging.LoggerFactory; import org.zbus.common.protocol.ConsumerInfo; import org.zbus.common.remoting.Message; import org.zbus.common.remoting.nio.Session; public class RequestQueue extends MessageQueue { private static final long serialVersionUID = -7640938066598234399L; private static final Logger log = LoggerFactory.getLogger(RequestQueue.class); protected final BlockingQueue<Message> msgQ = new LinkedBlockingQueue<Message>(); transient BlockingQueue<PullSession> sessQ = new LinkedBlockingQueue<PullSession>(); public RequestQueue(String broker, String name, ExecutorService executor, int mode){ super(broker, name, executor, mode); } void enqueue(final Message msg) { msgQ.offer(msg); executor.submit(new Runnable() { @Override public void run() { try{ if(messageStore != null){ messageStore.saveMessage(msg); } } catch (Exception e){ log.error(e.getMessage(), e); } } }); } Message dequeue() { final Message msg = msgQ.poll(); if(msg != null){ executor.submit(new Runnable() { @Override public void run() { try{ if(messageStore != null){ messageStore.removeMessage(msg); } } catch (Exception e){ log.error(e.getMessage(), e); } } }); } return msg; } public void produce(Message msg, Session sess) throws IOException{ String msgId = msg.getMsgId(); if(msg.isAck()){ ReplyHelper.reply200(msgId, sess); } enqueue(msg); this.dispatch(); } public void consume(Message msg, Session sess) throws IOException{ for(PullSession pull : sessQ){ if(pull.getSession() == sess){ pull.setPullMsg(msg); this.dispatch(); return; } } PullSession pull = new PullSession(sess, msg); sessQ.offer(pull); this.dispatch(); } public void cleanSession(){ Iterator<PullSession> iter = sessQ.iterator(); while(iter.hasNext()){ PullSession ps = iter.next(); if(!ps.session.isActive()){ iter.remove(); } } } @Override void doDispatch() throws IOException{ while(msgQ.peek() != null && sessQ.peek() != null){ PullSession pull = sessQ.poll(); if(pull == null || pull.window.get() == 0){ continue; } if( !pull.getSession().isActive() ){ continue; } Message msg = dequeue(); if(msg == null){ continue; } try { Message pullMsg = pull.getPullMsg(); Message writeMsg = Message.copyWithoutBody(msg); prepareMessageStatus(writeMsg); writeMsg.setMsgIdRaw(msg.getMsgId()); //保留原始消息ID writeMsg.setMsgId(pullMsg.getMsgId()); //配对订阅消息! pull.getSession().write(writeMsg); if(pull.window.get()>0){ pull.window.decrementAndGet(); } } catch (IOException ex) { log.error(ex.getMessage(), ex); enqueue(msg); } if(pull.window.get() == -1 || pull.window.get() > 0){ sessQ.offer(pull); } } } public void loadMessageList(List<Message> msgs){ this.msgQ.clear(); this.msgQ.addAll(msgs); } public List<ConsumerInfo> getConsumerInfoList() { List<ConsumerInfo> res = new ArrayList<ConsumerInfo>(); Iterator<PullSession> it = sessQ.iterator(); while(it.hasNext()){ PullSession value = it.next(); Session sess = value.getSession(); ConsumerInfo info = new ConsumerInfo(); info.setStatus(sess.getStatus().toString()); info.setRemoteAddr(sess.getRemoteAddress()); res.add(info); } return res; } @Override public int getMessageQueueSize() { return this.msgQ.size(); } }