Introduced the FlightZone concept (inbound and outbound) and separated logic of storage system.
This commit is contained in:
@@ -47,7 +47,7 @@ final class BrokerInterceptor implements Interceptor {
|
||||
private final ExecutorService executor;
|
||||
|
||||
private BrokerInterceptor(int poolSize, List<InterceptHandler> handlers) {
|
||||
LOG.info("Initializing broker interceptor. InterceptorIds = {}.", getInterceptorIds(handlers));
|
||||
LOG.info("Initializing broker interceptor. InterceptorIds={}", getInterceptorIds(handlers));
|
||||
this.handlers = new HashMap<>();
|
||||
for (Class<?> messageType : InterceptHandler.ALL_MESSAGE_TYPES) {
|
||||
this.handlers.put(messageType, new CopyOnWriteArrayList<InterceptHandler>());
|
||||
@@ -94,10 +94,8 @@ final class BrokerInterceptor implements Interceptor {
|
||||
@Override
|
||||
public void notifyClientConnected(final MqttConnectMessage msg) {
|
||||
for (final InterceptHandler handler : this.handlers.get(InterceptConnectMessage.class)) {
|
||||
LOG.debug(
|
||||
"Sending MQTT CONNECT message to interceptor. MqttClientId = {}, interceptorId = {}.",
|
||||
msg.payload().clientIdentifier(),
|
||||
handler.getID());
|
||||
LOG.debug("Sending MQTT CONNECT message to interceptor. CId={}, interceptorId={}",
|
||||
msg.payload().clientIdentifier(), handler.getID());
|
||||
executor.execute(new Runnable() {
|
||||
|
||||
@Override
|
||||
@@ -111,12 +109,8 @@ final class BrokerInterceptor implements Interceptor {
|
||||
@Override
|
||||
public void notifyClientDisconnected(final String clientID, final String username) {
|
||||
for (final InterceptHandler handler : this.handlers.get(InterceptDisconnectMessage.class)) {
|
||||
LOG.debug(
|
||||
"Notifying MQTT client disconnection to interceptor. MqttClientId = {}, username = {}, "
|
||||
+ "interceptorId = {}.",
|
||||
clientID,
|
||||
username,
|
||||
handler.getID());
|
||||
LOG.debug("Notifying MQTT client disconnection to interceptor. CId={}, username={}, interceptorId={}",
|
||||
clientID, username, handler.getID());
|
||||
executor.execute(new Runnable() {
|
||||
|
||||
@Override
|
||||
@@ -130,12 +124,8 @@ final class BrokerInterceptor implements Interceptor {
|
||||
@Override
|
||||
public void notifyClientConnectionLost(final String clientID, final String username) {
|
||||
for (final InterceptHandler handler : this.handlers.get(InterceptConnectionLostMessage.class)) {
|
||||
LOG.debug(
|
||||
"Notifying unexpected MQTT client disconnection to interceptor. MqttClientId = {}, "
|
||||
+ "username = {}, interceptorId = {}.",
|
||||
clientID,
|
||||
username,
|
||||
handler.getID());
|
||||
LOG.debug("Notifying unexpected MQTT client disconnection to interceptor CId={}, username={}, " +
|
||||
"interceptorId={}", clientID, username, handler.getID());
|
||||
executor.execute(new Runnable() {
|
||||
|
||||
@Override
|
||||
@@ -151,13 +141,8 @@ final class BrokerInterceptor implements Interceptor {
|
||||
int messageId = msg.variableHeader().messageId();
|
||||
String topic = msg.variableHeader().topicName();
|
||||
for (final InterceptHandler handler : this.handlers.get(InterceptPublishMessage.class)) {
|
||||
LOG.debug(
|
||||
"Notifying MQTT PUBLISH message to interceptor. MqttClientId = {}, messageId = {}, topic = {}, "
|
||||
+ "interceptorId = {}.",
|
||||
clientID,
|
||||
messageId,
|
||||
topic,
|
||||
handler.getID());
|
||||
LOG.debug("Notifying MQTT PUBLISH message to interceptor. CId={}, messageId={}, topic={}, interceptorId={}",
|
||||
clientID, messageId, topic, handler.getID());
|
||||
executor.execute(new Runnable() {
|
||||
|
||||
@Override
|
||||
@@ -171,12 +156,8 @@ final class BrokerInterceptor implements Interceptor {
|
||||
@Override
|
||||
public void notifyTopicSubscribed(final Subscription sub, final String username) {
|
||||
for (final InterceptHandler handler : this.handlers.get(InterceptSubscribeMessage.class)) {
|
||||
LOG.debug(
|
||||
"Notifying MQTT SUBSCRIBE message to interceptor. MqttClientId = {}, topicFilter = {}, "
|
||||
+ "interceptorId = {}.",
|
||||
sub.getClientId(),
|
||||
sub.getTopicFilter(),
|
||||
handler.getID());
|
||||
LOG.debug("Notifying MQTT SUBSCRIBE message to interceptor. CId={}, topicFilter={}, interceptorId={}",
|
||||
sub.getClientId(), sub.getTopicFilter(), handler.getID());
|
||||
executor.execute(new Runnable() {
|
||||
|
||||
@Override
|
||||
@@ -190,12 +171,8 @@ final class BrokerInterceptor implements Interceptor {
|
||||
@Override
|
||||
public void notifyTopicUnsubscribed(final String topic, final String clientID, final String username) {
|
||||
for (final InterceptHandler handler : this.handlers.get(InterceptUnsubscribeMessage.class)) {
|
||||
LOG.debug(
|
||||
"Notifying MQTT UNSUBSCRIBE message to interceptor. MqttClientId = {}, topic = {}, "
|
||||
+ "interceptorId = {}.",
|
||||
clientID,
|
||||
topic,
|
||||
handler.getID());
|
||||
LOG.debug("Notifying MQTT UNSUBSCRIBE message to interceptor. CId={}, topic={}, interceptorId={}", clientID,
|
||||
topic, handler.getID());
|
||||
executor.execute(new Runnable() {
|
||||
|
||||
@Override
|
||||
@@ -209,13 +186,8 @@ final class BrokerInterceptor implements Interceptor {
|
||||
@Override
|
||||
public void notifyMessageAcknowledged(final InterceptAcknowledgedMessage msg) {
|
||||
for (final InterceptHandler handler : this.handlers.get(InterceptAcknowledgedMessage.class)) {
|
||||
LOG.debug(
|
||||
"Notifying MQTT ACK message to interceptor. MqttClientId = {}, messageId = {}, topic = {}, "
|
||||
+ "interceptorId = {}.",
|
||||
msg.getMsg().getClientID(),
|
||||
msg.getMsg().getMessageID(),
|
||||
msg.getTopic(),
|
||||
handler.getID());
|
||||
LOG.debug("Notifying MQTT ACK message to interceptor. CId={}, messageId={}, topic={}, interceptorId={}",
|
||||
msg.getMsg().getClientID(), msg.getPacketID(), msg.getTopic(), handler.getID());
|
||||
executor.execute(new Runnable() {
|
||||
|
||||
@Override
|
||||
@@ -229,10 +201,8 @@ final class BrokerInterceptor implements Interceptor {
|
||||
@Override
|
||||
public void addInterceptHandler(InterceptHandler interceptHandler) {
|
||||
Class<?>[] interceptedMessageTypes = getInterceptedMessageTypes(interceptHandler);
|
||||
LOG.info(
|
||||
"Adding MQTT message interceptor. InterceptorId = {}, handledMessageTypes = {}.",
|
||||
interceptHandler.getID(),
|
||||
interceptedMessageTypes);
|
||||
LOG.info( "Adding MQTT message interceptor. InterceptorId={}, handledMessageTypes={}",
|
||||
interceptHandler.getID(), interceptedMessageTypes);
|
||||
for (Class<?> interceptMessageType : interceptedMessageTypes) {
|
||||
this.handlers.get(interceptMessageType).add(interceptHandler);
|
||||
}
|
||||
@@ -241,10 +211,8 @@ final class BrokerInterceptor implements Interceptor {
|
||||
@Override
|
||||
public void removeInterceptHandler(InterceptHandler interceptHandler) {
|
||||
Class<?>[] interceptedMessageTypes = getInterceptedMessageTypes(interceptHandler);
|
||||
LOG.info(
|
||||
"Removing MQTT message interceptor. InterceptorId = {}, handledMessageTypes = {}.",
|
||||
interceptHandler.getID(),
|
||||
interceptedMessageTypes);
|
||||
LOG.info("Removing MQTT message interceptor. InterceptorId={}, handledMessageTypes={}",
|
||||
interceptHandler.getID(), interceptedMessageTypes);
|
||||
for (Class<?> interceptMessageType : interceptedMessageTypes) {
|
||||
this.handlers.get(interceptMessageType).remove(interceptHandler);
|
||||
}
|
||||
|
||||
@@ -25,17 +25,16 @@ class InternalRepublisher {
|
||||
void publishRetained(ClientSession targetSession, Collection<IMessagesStore.StoredMessage> messages) {
|
||||
for (IMessagesStore.StoredMessage storedMsg : messages) {
|
||||
// fire as retained the message
|
||||
Integer packetID = storedMsg.getQos() == MqttQoS.AT_MOST_ONCE ? null : targetSession.nextPacketId();
|
||||
if (packetID != null) {
|
||||
LOG.debug("Adding message to inflight zone. ClientId={}, packetId={}, messageId={}, topic={}",
|
||||
targetSession.clientID, packetID, storedMsg.getMessageID(), storedMsg.getTopic());
|
||||
targetSession.inFlightAckWaiting(storedMsg.getGuid(), packetID);
|
||||
}
|
||||
MqttPublishMessage publishMsg = retainedPublish(storedMsg);
|
||||
// set the PacketIdentifier only for QoS > 0
|
||||
if (publishMsg.fixedHeader().qosLevel() != MqttQoS.AT_MOST_ONCE) {
|
||||
if (storedMsg.getQos() != MqttQoS.AT_MOST_ONCE) {
|
||||
LOG.debug("Adding message to inflight zone. ClientId={}, topic={}", targetSession.clientID,
|
||||
storedMsg.getTopic());
|
||||
int packetID = targetSession.inFlightAckWaiting(storedMsg.getGuid());
|
||||
|
||||
// set the PacketIdentifier only for QoS > 0
|
||||
publishMsg = retainedPublish(storedMsg, packetID);
|
||||
}
|
||||
|
||||
this.messageSender.sendPublish(targetSession, publishMsg);
|
||||
}
|
||||
}
|
||||
@@ -46,13 +45,13 @@ class InternalRepublisher {
|
||||
|
||||
for (IMessagesStore.StoredMessage pubEvt : storedPublishes) {
|
||||
// put in flight zone
|
||||
LOG.debug("Adding message ot inflight zone. ClientId={}, guid={}, messageId={}, topic={}",
|
||||
clientSession.clientID, pubEvt.getGuid(), pubEvt.getMessageID(), pubEvt.getTopic());
|
||||
clientSession.inFlightAckWaiting(pubEvt.getGuid(), pubEvt.getMessageID());
|
||||
LOG.debug("Adding message ot inflight zone. ClientId={}, guid={}, topic={}", clientSession.clientID,
|
||||
pubEvt.getGuid(), pubEvt.getTopic());
|
||||
int messageId = clientSession.inFlightAckWaiting(pubEvt.getGuid());
|
||||
MqttPublishMessage publishMsg = notRetainedPublish(pubEvt);
|
||||
// set the PacketIdentifier only for QoS > 0
|
||||
if (publishMsg.fixedHeader().qosLevel() != MqttQoS.AT_MOST_ONCE) {
|
||||
publishMsg = notRetainedPublish(pubEvt, pubEvt.getMessageID());
|
||||
publishMsg = notRetainedPublish(pubEvt, messageId);
|
||||
}
|
||||
this.messageSender.sendPublish(clientSession, publishMsg);
|
||||
}
|
||||
|
||||
@@ -63,25 +63,20 @@ class MessagesPublisher {
|
||||
// refCnt = 0
|
||||
ByteBuf message = origMessage.retainedDuplicate();
|
||||
if (targetIsActive) {
|
||||
LOG.debug(
|
||||
"Sending PUBLISH message to active subscriber. MessageId={}, CId={}, topicFilter={}, qos={}",
|
||||
pubMsg.getMessageID(),
|
||||
sub.getClientId(),
|
||||
sub.getTopicFilter(),
|
||||
qos);
|
||||
LOG.debug("Sending PUBLISH message to active subscriber. CId={}, topicFilter={}, qos={}",
|
||||
sub.getClientId(), sub.getTopicFilter(), qos);
|
||||
MqttPublishMessage publishMsg = notRetainedPublish(topic, qos, message);
|
||||
if (qos != MqttQoS.AT_MOST_ONCE) {
|
||||
// QoS 1 or 2
|
||||
int messageId = targetSession.nextPacketId();
|
||||
targetSession.inFlightAckWaiting(guid, messageId);
|
||||
int messageId = targetSession.inFlightAckWaiting(guid);
|
||||
// set the PacketIdentifier only for QoS > 0
|
||||
publishMsg = notRetainedPublishWithMessageId(topic, qos, message, messageId);
|
||||
}
|
||||
this.messageSender.sendPublish(targetSession, publishMsg);
|
||||
} else {
|
||||
if (!targetSession.isCleanSession()) {
|
||||
LOG.debug("Storing pending PUBLISH inactive message. MessageId={}, CId={}, topicFilter={}, qos={}",
|
||||
pubMsg.getMessageID(), sub.getClientId(), sub.getTopicFilter(), qos);
|
||||
LOG.debug("Storing pending PUBLISH inactive message. CId={}, topicFilter={}, qos={}",
|
||||
sub.getClientId(), sub.getTopicFilter(), qos);
|
||||
// store the message in targetSession queue to deliver
|
||||
targetSession.enqueue(pubMsg);
|
||||
}
|
||||
|
||||
@@ -474,7 +474,7 @@ public class ProtocolProcessor {
|
||||
targetSession.inFlightAcknowledged(messageID);
|
||||
|
||||
String topic = inflightMsg.getTopic();
|
||||
m_interceptor.notifyMessageAcknowledged(new InterceptAcknowledgedMessage(inflightMsg, topic, username));
|
||||
m_interceptor.notifyMessageAcknowledged(new InterceptAcknowledgedMessage(inflightMsg, topic, username, messageID));
|
||||
}
|
||||
|
||||
public static IMessagesStore.StoredMessage asStoredMessage(MqttPublishMessage msg) {
|
||||
@@ -485,7 +485,6 @@ public class ProtocolProcessor {
|
||||
IMessagesStore.StoredMessage stored = new IMessagesStore.StoredMessage(payloadContent,
|
||||
msg.fixedHeader().qosLevel(), msg.variableHeader().topicName());
|
||||
stored.setRetained(msg.fixedHeader().isRetain());
|
||||
stored.setMessageID(msg.variableHeader().messageId());
|
||||
return stored;
|
||||
}
|
||||
|
||||
@@ -540,7 +539,6 @@ public class ProtocolProcessor {
|
||||
} else {
|
||||
toStoreMsg.setClientID(clientId);
|
||||
}
|
||||
toStoreMsg.setMessageID(1);
|
||||
if (qos == EXACTLY_ONCE) { // QoS2
|
||||
guid = m_messagesStore.storePublishForFuture(toStoreMsg);
|
||||
}
|
||||
@@ -568,18 +566,12 @@ public class ProtocolProcessor {
|
||||
private void forwardPublishWill(WillMessage will, String clientID) {
|
||||
// it has just to publish the message downstream to the subscribers
|
||||
// NB it's a will publish, it needs a PacketIdentifier for this conn, default to 1
|
||||
Integer messageId = null;
|
||||
if (will.getQos() != AT_MOST_ONCE) {
|
||||
messageId = m_sessionsStore.nextPacketID(clientID);
|
||||
}
|
||||
|
||||
IMessagesStore.StoredMessage tobeStored = asStoredMessage(will);
|
||||
tobeStored.setClientID(clientID);
|
||||
tobeStored.setMessageID(messageId);
|
||||
Topic topic = new Topic(tobeStored.getTopic());
|
||||
List<Subscription> topicMatchingSubscriptions = subscriptions.matches(topic);
|
||||
|
||||
LOG.info("Publishing will message. CId={}, messageId={}, topic={}", clientID, messageId, topic);
|
||||
LOG.info("Publishing will message. CId={}, topic={}", clientID, topic);
|
||||
this.messagesPublisher.publish2Subscribers(tobeStored, topicMatchingSubscriptions);
|
||||
}
|
||||
|
||||
@@ -626,7 +618,7 @@ public class ProtocolProcessor {
|
||||
StoredMessage inflightMsg = targetSession.secondPhaseAcknowledged(messageID);
|
||||
String username = NettyUtils.userName(channel);
|
||||
String topic = inflightMsg.getTopic();
|
||||
m_interceptor.notifyMessageAcknowledged(new InterceptAcknowledgedMessage(inflightMsg, topic, username));
|
||||
m_interceptor.notifyMessageAcknowledged(new InterceptAcknowledgedMessage(inflightMsg, topic, username, messageID));
|
||||
}
|
||||
|
||||
public void processDisconnect(Channel channel) throws InterruptedException {
|
||||
@@ -759,8 +751,7 @@ public class ProtocolProcessor {
|
||||
if (!validTopic) {
|
||||
// close the connection, not valid topicFilter is a protocol violation
|
||||
channel.close();
|
||||
LOG.error( "Topic filter is not valid. CId={}, topics={}, badTopicFilter={}", clientID, topics,
|
||||
topic);
|
||||
LOG.error("Topic filter is not valid. CId={}, topics={}, badTopicFilter={}", clientID, topics, topic);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -16,6 +16,8 @@ import io.netty.handler.codec.mqtt.*;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import java.util.List;
|
||||
|
||||
import static io.moquette.spi.impl.DebugUtils.payload2Str;
|
||||
import static io.moquette.spi.impl.ProtocolProcessor.asStoredMessage;
|
||||
import static io.moquette.spi.impl.Utils.messageId;
|
||||
import static io.netty.handler.codec.mqtt.MqttMessageIdVariableHeader.from;
|
||||
@@ -23,7 +25,7 @@ import static io.netty.handler.codec.mqtt.MqttQoS.AT_MOST_ONCE;
|
||||
|
||||
class Qos2PublishHandler extends QosPublishHandler {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(Qos1PublishHandler.class);
|
||||
private static final Logger LOG = LoggerFactory.getLogger(Qos2PublishHandler.class);
|
||||
|
||||
private final SubscriptionsStore subscriptions;
|
||||
private final IMessagesStore m_messagesStore;
|
||||
@@ -57,18 +59,16 @@ class Qos2PublishHandler extends QosPublishHandler {
|
||||
String clientID = NettyUtils.clientID(channel);
|
||||
toStoreMsg.setClientID(clientID);
|
||||
|
||||
LOG.info("Sending publish message to subscribers CId={}, topic={}, messageId={}", clientID, topic, messageID);
|
||||
if (LOG.isTraceEnabled()) {
|
||||
LOG.trace( "Sending publish message to subscribers. ClientId={}, topic={}, messageId={}, payload={}, " +
|
||||
"subscriptionTree={}", clientID, topic, messageID, DebugUtils.payload2Str(toStoreMsg.getMessage()),
|
||||
subscriptions.dumpTree());
|
||||
} else {
|
||||
LOG.info("Sending publish message to subscribers. ClientId={}, topic={}, messageId={}", clientID, topic,
|
||||
messageID);
|
||||
LOG.trace("payload={}, subs Tree={}", payload2Str(toStoreMsg.getMessage()), subscriptions.dumpTree());
|
||||
}
|
||||
|
||||
// QoS2
|
||||
MessageGUID guid = m_messagesStore.storePublishForFuture(toStoreMsg);
|
||||
// TODO Don't send PUBREC for Hz publish notification, if (msg.isLocal()) {
|
||||
ClientSession sourceSession = m_sessionsStore.sessionForClient(clientID);
|
||||
sourceSession.markAsInboundInflight(messageID, guid);
|
||||
|
||||
sendPubRec(clientID, messageID);
|
||||
|
||||
// Next the client will send us a pub rel
|
||||
@@ -92,18 +92,22 @@ class Qos2PublishHandler extends QosPublishHandler {
|
||||
void processPubRel(Channel channel, MqttMessage msg) {
|
||||
String clientID = NettyUtils.clientID(channel);
|
||||
int messageID = messageId(msg);
|
||||
LOG.info("Processing PUBREL message. ClientId={}, messageId={}", clientID, messageID);
|
||||
LOG.info("Processing PUBREL message. CId={}, messageId={}", clientID, messageID);
|
||||
ClientSession targetSession = m_sessionsStore.sessionForClient(clientID);
|
||||
IMessagesStore.StoredMessage evt = targetSession.storedMessage(messageID);
|
||||
IMessagesStore.StoredMessage evt = targetSession.inboundInflight(messageID);
|
||||
if (evt == null) {
|
||||
LOG.warn("Can't find inbound inflight message for CId={}, messageId={}", clientID, messageID);
|
||||
throw new IllegalArgumentException("Can't find inbound inflight message");
|
||||
}
|
||||
final Topic topic = new Topic(evt.getTopic());
|
||||
List<Subscription> topicMatchingSubscriptions = subscriptions.matches(topic);
|
||||
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("Sending publish message to subscribers. ClientId={}, topic={}, messageId={}, payload={}, " +
|
||||
"subscriptionTree={}", clientID, topic, messageID, DebugUtils.payload2Str(evt.getMessage()),
|
||||
LOG.debug("Sending publish message to subscribers. CId={}, topic={}, messageId={}, payload={}, " +
|
||||
"subscriptionTree={}", clientID, topic, messageID, payload2Str(evt.getMessage()),
|
||||
subscriptions.dumpTree());
|
||||
} else {
|
||||
LOG.info("Sending publish message to subscribers. ClientId={}, topic={}, messageId={}", clientID, topic,
|
||||
LOG.info("Sending publish message to subscribers. CId={}, topic={}, messageId={}", clientID, topic,
|
||||
messageID);
|
||||
}
|
||||
this.publisher.publish2Subscribers(evt, topicMatchingSubscriptions);
|
||||
@@ -120,14 +124,14 @@ class Qos2PublishHandler extends QosPublishHandler {
|
||||
}
|
||||
|
||||
private void sendPubRec(String clientID, int messageID) {
|
||||
LOG.debug("Sending PUBREC message. ClientId={}, messageId={}", clientID, messageID);
|
||||
LOG.debug("Sending PUBREC message. CId={}, messageId={}", clientID, messageID);
|
||||
MqttFixedHeader fixedHeader = new MqttFixedHeader(MqttMessageType.PUBREC, false, AT_MOST_ONCE, false, 0);
|
||||
MqttMessage pubRecMessage = new MqttMessage(fixedHeader, from(messageID));
|
||||
connectionDescriptors.sendMessage(pubRecMessage, messageID, clientID);
|
||||
}
|
||||
|
||||
private void sendPubComp(String clientID, int messageID) {
|
||||
LOG.debug("Sending PUBCOMP message. ClientId={}, messageId={}", clientID, messageID);
|
||||
LOG.debug("Sending PUBCOMP message. CId={}, messageId={}", clientID, messageID);
|
||||
MqttFixedHeader fixedHeader = new MqttFixedHeader(MqttMessageType.PUBCOMP, false, AT_MOST_ONCE, false, 0);
|
||||
MqttMessage pubCompMessage = new MqttMessage(fixedHeader, from(messageID));
|
||||
connectionDescriptors.sendMessage(pubCompMessage, messageID, clientID);
|
||||
|
||||
Reference in New Issue
Block a user