Added output reactor to isolate the writing of messages
This commit is contained in:
+52
-9
@@ -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) {
|
||||||
|
|||||||
+28
@@ -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());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user