@Override public void dispatchForSync(Message msg) { if (msg != null) { final MessageHandler handler = msg.getMessageHandler(); // cant be null NonBlockingSession session = (NonBlockingSession) handler; MessageQueue queue = session.getSendSyncQueue(); if (queue != null) { queue.add(msg); } else { // @TODO add ReusableString write( ReusableString buf ) to Message and log details // should NEVER happen _log.error(MISSING_HANDLER, ((Session) handler).getComponentId()); } } }
@Override public void setStopping() { // dont actually stop, but wake up to force flush final int numSessions = _sessions.length; for (int i = 0; i < numSessions; i++) { final SessionWrapper s = _sessions[i]; MessageQueue q = s._queue; q.add(new NullMessage()); // wake up queue } _fullyFlushed = false; }
@Override public void stop() { if (_stopping.compareAndSet(false, true)) { _ctl.setStopping(true); final int numSessions = _sessions.length; for (int i = 0; i < numSessions; i++) { final SessionWrapper s = _sessions[i]; MessageQueue q = s._queue; q.add(new NullMessage()); // wake up queue } _fullyFlushed = false; } }
@Override public void dispatch(final Message msg) { if (msg != null) { final MessageHandler handler = msg.getMessageHandler(); final NonBlockingSession session = (NonBlockingSession) handler; final MessageQueue queue = session.getSendQueue(); if (queue != null) { queue.add(msg); } else { // should NEVER happen ReusableString s = TLC.instance().pop(); s.copy(((Session) handler).getComponentId()) .append(": Missing Queue, unable to dispatch : "); msg.dump(s); _log.error(MISSING_HANDLER, s); TLC.instance().pushback(s); } } }
// @NOTE keep flush private the preQ is not threadsafe private void flush(SessionWrapper sessW) { // disconnected drop any session messages // optionally keep any other messages or reject back upstream final Session session = sessW._session; final MessageQueue queue = sessW._queue; final MessageQueue preQ = sessW._preQueue; final MessageQueue syncQ = sessW._syncQueue; while (!syncQ.isEmpty()) { syncQ.next(); // DISCARD } Message head = null; Message tail = null; while (!queue.isEmpty()) { Message msg = queue.next(); if (msg.getReusableType() == CoreReusableType.NullMessage) break; if (session.discardOnDisconnect(msg) == false) { if (session.rejectMessageUpstream(msg, DISCONNECTED)) { // message recycled by successful reject processing } else { if (tail == null) { head = msg; tail = msg; } else { tail.attachQueue(msg); tail = msg; } } } else { _logMsg.copy(DROP_MSG).append(msg.getReusableType().toString()); _log.info(_logMsg); session.outboundRecycle(msg); } } // move remaining messages to the preQ if (head != null) { Message tmp = head; while (tmp != null) { Message next = tmp.getNextQueueEntry(); tmp.detachQueue(); preQ.add(tmp); tmp = next; } } }
@Override public void execute() throws Exception { _curSessW = _sessions[_nextSession]; final MessageQueue queue = _curSessW._queue; final MessageQueue preQueue = _curSessW._preQueue; final NonBlockingSession sess = _curSessW._session; if (++_nextSession >= _sessions.length) _nextSession = 0; if (_curSessW._connected && sess.canHandle()) { if (sess.isLoggedIn()) { if (sess.isMsgPendingWrite()) { sess.retryCompleteWrite(); } else if (preQueue.isEmpty()) { _curMsg = queue.poll(); // POLL = non blocking, causes MEM_READ barrier if (_curMsg != null && _curMsg.getReusableType() != CoreReusableType.NullMessage) { sess.handleNow(_curMsg); } } else { // QUEUED MESSAGES FROM PREVIOUS FLUSH CALLS _curMsg = preQueue.next(); if (_curMsg.getReusableType() != CoreReusableType.NullMessage) { sess.handleNow(_curMsg); } } } else { // SYNC mode final MessageQueue syncQueue = _curSessW._syncQueue; if (sess.isMsgPendingWrite()) { sess.retryCompleteWrite(); } else if (!syncQueue.isEmpty()) { _curMsg = syncQueue.next(); if (_curMsg.getReusableType() != CoreReusableType.NullMessage) { sess.handleNow(_curMsg); } } } } else { flush(_curSessW); } }