Added output reactor to isolate the writing of messages

This commit is contained in:
andrea
2013-11-14 16:43:03 +01:00
parent 7a7c5cc53e
commit 817ca8e176
4 changed files with 83 additions and 13 deletions
@@ -1,11 +1,19 @@
package org.dna.mqtt.moquette.messaging.spi.impl; package org.dna.mqtt.moquette.messaging.spi.impl;
import com.lmax.disruptor.BatchEventProcessor;
import com.lmax.disruptor.EventHandler;
import com.lmax.disruptor.RingBuffer;
import com.lmax.disruptor.SequenceBarrier;
import java.util.Collection; import java.util.Collection;
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 java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import org.dna.mqtt.moquette.messaging.spi.IMatchingCondition; import org.dna.mqtt.moquette.messaging.spi.IMatchingCondition;
import org.dna.mqtt.moquette.messaging.spi.IStorageService; import org.dna.mqtt.moquette.messaging.spi.IStorageService;
import org.dna.mqtt.moquette.messaging.spi.impl.events.MessagingEvent;
import org.dna.mqtt.moquette.messaging.spi.impl.events.OutputMessagingEvent;
import org.dna.mqtt.moquette.messaging.spi.impl.events.PubAckEvent; import org.dna.mqtt.moquette.messaging.spi.impl.events.PubAckEvent;
import org.dna.mqtt.moquette.messaging.spi.impl.events.PublishEvent; import org.dna.mqtt.moquette.messaging.spi.impl.events.PublishEvent;
import org.dna.mqtt.moquette.messaging.spi.impl.subscriptions.Subscription; import org.dna.mqtt.moquette.messaging.spi.impl.subscriptions.Subscription;
@@ -36,7 +44,7 @@ import org.slf4j.LoggerFactory;
* *
* @author andrea * @author andrea
*/ */
class ProtocolProcessor { class ProtocolProcessor implements EventHandler<ValueEvent> {
private static final Logger LOG = LoggerFactory.getLogger(ProtocolProcessor.class); private static final Logger LOG = LoggerFactory.getLogger(ProtocolProcessor.class);
@@ -44,16 +52,29 @@ class ProtocolProcessor {
private SubscriptionsStore subscriptions; private SubscriptionsStore subscriptions;
private IStorageService m_storageService; private IStorageService m_storageService;
private IAuthenticator m_authenticator; private IAuthenticator m_authenticator;
private ExecutorService m_executor;
BatchEventProcessor<ValueEvent> m_eventProcessor;
private RingBuffer<ValueEvent> m_ringBuffer;
ProtocolProcessor() { ProtocolProcessor() {}
}
void init(/*Map<String, ConnectionDescriptor> clientIDs, */SubscriptionsStore subscriptions, void init(/*Map<String, ConnectionDescriptor> clientIDs, */SubscriptionsStore subscriptions,
IStorageService storageService) { IStorageService storageService) {
//m_clientIDs = clientIDs; //m_clientIDs = clientIDs;
this.subscriptions = subscriptions; this.subscriptions = subscriptions;
m_storageService = storageService; m_storageService = storageService;
//init the output ringbuffer
m_executor = Executors.newFixedThreadPool(1);
m_ringBuffer = new RingBuffer<ValueEvent>(ValueEvent.EVENT_FACTORY, 1024 * 32);
SequenceBarrier barrier = m_ringBuffer.newBarrier();
m_eventProcessor = new BatchEventProcessor<ValueEvent>(m_ringBuffer, barrier, this);
//TODO in a presentation is said to don't do the followinf line!!
m_ringBuffer.setGatingSequences(m_eventProcessor.getSequence());
m_executor.submit(m_eventProcessor);
} }
void processConnect(ServerChannel session, ConnectMessage msg) { void processConnect(ServerChannel session, ConnectMessage msg) {
@@ -253,7 +274,8 @@ class ProtocolProcessor {
throw new RuntimeException(String.format("Can't find a ConnectionDescriptor for client %s in cache %s", clientId, m_clientIDs)); throw new RuntimeException(String.format("Can't find a ConnectionDescriptor for client %s in cache %s", clientId, m_clientIDs));
} }
LOG.debug("Session for clientId " + clientId + " is " + m_clientIDs.get(clientId).getSession()); LOG.debug("Session for clientId " + clientId + " is " + m_clientIDs.get(clientId).getSession());
m_clientIDs.get(clientId).getSession().write(pubMessage); // m_clientIDs.get(clientId).getSession().write(pubMessage);
disruptorPublish(new OutputMessagingEvent(m_clientIDs.get(clientId).getSession(), pubMessage));
}catch(Throwable t) { }catch(Throwable t) {
LOG.error(null, t); LOG.error(null, t);
} }
@@ -264,7 +286,8 @@ class ProtocolProcessor {
PubRecMessage pubRecMessage = new PubRecMessage(); PubRecMessage pubRecMessage = new PubRecMessage();
pubRecMessage.setMessageID(messageID); pubRecMessage.setMessageID(messageID);
m_clientIDs.get(clientID).getSession().write(pubRecMessage); // m_clientIDs.get(clientID).getSession().write(pubRecMessage);
disruptorPublish(new OutputMessagingEvent(m_clientIDs.get(clientID).getSession(), pubRecMessage));
} }
private void sendPubAck(PubAckEvent evt) { private void sendPubAck(PubAckEvent evt) {
@@ -284,7 +307,8 @@ class ProtocolProcessor {
throw new RuntimeException(String.format("Can't find a ConnectionDEwcriptor for client %s in cache %s", clientId, m_clientIDs)); throw new RuntimeException(String.format("Can't find a ConnectionDEwcriptor for client %s in cache %s", clientId, m_clientIDs));
} }
LOG.debug("Session for clientId " + clientId + " is " + m_clientIDs.get(clientId).getSession()); LOG.debug("Session for clientId " + clientId + " is " + m_clientIDs.get(clientId).getSession());
m_clientIDs.get(clientId).getSession().write(pubAckMessage); // m_clientIDs.get(clientId).getSession().write(pubAckMessage);
disruptorPublish(new OutputMessagingEvent(m_clientIDs.get(clientId).getSession(), pubAckMessage));
}catch(Throwable t) { }catch(Throwable t) {
LOG.error(null, t); LOG.error(null, t);
} }
@@ -319,7 +343,8 @@ class ProtocolProcessor {
PubCompMessage pubCompMessage = new PubCompMessage(); PubCompMessage pubCompMessage = new PubCompMessage();
pubCompMessage.setMessageID(messageID); pubCompMessage.setMessageID(messageID);
m_clientIDs.get(clientID).getSession().write(pubCompMessage); // m_clientIDs.get(clientID).getSession().write(pubCompMessage);
disruptorPublish(new OutputMessagingEvent(m_clientIDs.get(clientID).getSession(), pubCompMessage));
} }
void processPubRec(String clientID, int messageID) { void processPubRec(String clientID, int messageID) {
@@ -328,7 +353,8 @@ class ProtocolProcessor {
PubRelMessage pubRelMessage = new PubRelMessage(); PubRelMessage pubRelMessage = new PubRelMessage();
pubRelMessage.setMessageID(messageID); pubRelMessage.setMessageID(messageID);
m_clientIDs.get(clientID).getSession().write(pubRelMessage); // m_clientIDs.get(clientID).getSession().write(pubRelMessage);
disruptorPublish(new OutputMessagingEvent(m_clientIDs.get(clientID).getSession(), pubRelMessage));
} }
void processPubComp(String clientID, int messageID) { void processPubComp(String clientID, int messageID) {
@@ -407,5 +433,22 @@ class ProtocolProcessor {
sendPublish(newSubscription.getClientId(), storedMsg.getTopic(), storedMsg.getQos(), storedMsg.getPayload(), true); sendPublish(newSubscription.getClientId(), storedMsg.getTopic(), storedMsg.getQos(), storedMsg.getPayload(), true);
} }
} }
private void disruptorPublish(OutputMessagingEvent msgEvent) {
LOG.debug("disruptorPublish publishing event on output " + msgEvent);
long sequence = m_ringBuffer.next();
ValueEvent event = m_ringBuffer.get(sequence);
event.setEvent(msgEvent);
m_ringBuffer.publish(sequence);
}
public void onEvent(ValueEvent t, long l, boolean bln) throws Exception {
MessagingEvent evt = t.getEvent();
//It's always of type OutputMessagingEvent
OutputMessagingEvent outEvent = (OutputMessagingEvent) evt;
outEvent.getChannel().write(outEvent.getMessage());
}
} }
@@ -4,8 +4,6 @@ import com.lmax.disruptor.BatchEventProcessor;
import com.lmax.disruptor.EventHandler; import com.lmax.disruptor.EventHandler;
import com.lmax.disruptor.RingBuffer; import com.lmax.disruptor.RingBuffer;
import com.lmax.disruptor.SequenceBarrier; import com.lmax.disruptor.SequenceBarrier;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
import org.dna.mqtt.moquette.messaging.spi.IMessaging; import org.dna.mqtt.moquette.messaging.spi.IMessaging;
@@ -15,7 +13,6 @@ import org.dna.mqtt.moquette.messaging.spi.impl.subscriptions.SubscriptionsStore
import org.dna.mqtt.moquette.proto.messages.PubCompMessage; import org.dna.mqtt.moquette.proto.messages.PubCompMessage;
import org.dna.mqtt.moquette.proto.messages.*; import org.dna.mqtt.moquette.proto.messages.*;
import org.dna.mqtt.moquette.proto.messages.AbstractMessage.QOSType; import org.dna.mqtt.moquette.proto.messages.AbstractMessage.QOSType;
import org.dna.mqtt.moquette.server.ConnectionDescriptor;
import org.dna.mqtt.moquette.server.Constants; import org.dna.mqtt.moquette.server.Constants;
import org.dna.mqtt.moquette.server.ServerChannel; import org.dna.mqtt.moquette.server.ServerChannel;
import org.slf4j.Logger; import org.slf4j.Logger;
@@ -96,7 +93,7 @@ public class SimpleMessaging implements IMessaging, EventHandler<ValueEvent> {
public void onEvent(ValueEvent t, long l, boolean bln) throws Exception { public void onEvent(ValueEvent t, long l, boolean bln) throws Exception {
MessagingEvent evt = t.getEvent(); MessagingEvent evt = t.getEvent();
LOG.info("onEvent processing messaging event " + evt); LOG.info("onEvent processing messaging event from input ringbuffer" + evt);
if (evt instanceof PublishEvent) { if (evt instanceof PublishEvent) {
m_processor.processPublish((PublishEvent) evt); m_processor.processPublish((PublishEvent) evt);
} else if (evt instanceof StopEvent) { } else if (evt instanceof StopEvent) {
@@ -0,0 +1,28 @@
package org.dna.mqtt.moquette.messaging.spi.impl.events;
import org.dna.mqtt.moquette.proto.messages.AbstractMessage;
import org.dna.mqtt.moquette.server.ServerChannel;
/**
*
* @author andrea
*/
public class OutputMessagingEvent extends MessagingEvent {
private ServerChannel m_channel;
private AbstractMessage m_message;
public OutputMessagingEvent(ServerChannel channel, AbstractMessage message) {
m_channel = channel;
m_message = message;
}
public ServerChannel getChannel() {
return m_channel;
}
public AbstractMessage getMessage() {
return m_message;
}
}
@@ -315,6 +315,8 @@ public class ServerIntegrationPahoTest {
m_client.connect(options); m_client.connect(options);
assertNotNull(m_callback);
assertNotNull(m_callback.getMessage());
assertEquals("Hello MQTT", m_callback.getMessage().toString()); assertEquals("Hello MQTT", m_callback.getMessage().toString());
} }