Add 'getSubscriptions' API on Server.
Add a test for sessions without clean session flag.
This commit is contained in:
@@ -33,6 +33,7 @@ import io.moquette.server.config.FilesystemConfig;
|
|||||||
import io.moquette.server.config.IConfig;
|
import io.moquette.server.config.IConfig;
|
||||||
import io.moquette.server.netty.NettyAcceptor;
|
import io.moquette.server.netty.NettyAcceptor;
|
||||||
import io.moquette.spi.impl.ProtocolProcessor;
|
import io.moquette.spi.impl.ProtocolProcessor;
|
||||||
|
import io.moquette.spi.impl.subscriptions.Subscription;
|
||||||
import io.moquette.spi.security.IAuthenticator;
|
import io.moquette.spi.security.IAuthenticator;
|
||||||
import io.moquette.spi.security.IAuthorizator;
|
import io.moquette.spi.security.IAuthorizator;
|
||||||
import io.moquette.spi.security.ISslContextCreator;
|
import io.moquette.spi.security.ISslContextCreator;
|
||||||
@@ -211,6 +212,17 @@ public class Server {
|
|||||||
LOG.info("Server stopped");
|
LOG.info("Server stopped");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SPI method used by Broker embedded applications to get list of subscribers.
|
||||||
|
* Returns null if the broker is not started.
|
||||||
|
*/
|
||||||
|
public List<Subscription> getSubscriptions() {
|
||||||
|
if (m_processorBootstrapper == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return m_processorBootstrapper.getSubscriptions();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* SPI method used by Broker embedded applications to add intercept handlers.
|
* SPI method used by Broker embedded applications to add intercept handlers.
|
||||||
* */
|
* */
|
||||||
|
|||||||
@@ -94,6 +94,11 @@ public interface ISessionsStore {
|
|||||||
* */
|
* */
|
||||||
Subscription getSubscription(ClientTopicCouple couple);
|
Subscription getSubscription(ClientTopicCouple couple);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @return all subscriptions stored.
|
||||||
|
*/
|
||||||
|
List<Subscription> getSubscriptions();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return true iff there are subscriptions persisted with clientID
|
* @return true iff there are subscriptions persisted with clientID
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import io.moquette.interception.InterceptHandler;
|
|||||||
import io.moquette.server.config.IConfig;
|
import io.moquette.server.config.IConfig;
|
||||||
import io.moquette.spi.ISessionsStore;
|
import io.moquette.spi.ISessionsStore;
|
||||||
import io.moquette.spi.impl.security.*;
|
import io.moquette.spi.impl.security.*;
|
||||||
|
import io.moquette.spi.impl.subscriptions.Subscription;
|
||||||
import io.moquette.spi.impl.subscriptions.SubscriptionsStore;
|
import io.moquette.spi.impl.subscriptions.SubscriptionsStore;
|
||||||
import io.moquette.spi.persistence.MapDBPersistentStore;
|
import io.moquette.spi.persistence.MapDBPersistentStore;
|
||||||
import io.moquette.spi.security.IAuthenticator;
|
import io.moquette.spi.security.IAuthenticator;
|
||||||
@@ -50,6 +51,8 @@ public class ProtocolProcessorBootstrapper {
|
|||||||
|
|
||||||
private MapDBPersistentStore m_mapStorage;
|
private MapDBPersistentStore m_mapStorage;
|
||||||
|
|
||||||
|
private ISessionsStore m_sessionsStore;
|
||||||
|
|
||||||
private BrokerInterceptor m_interceptor;
|
private BrokerInterceptor m_interceptor;
|
||||||
|
|
||||||
private final ProtocolProcessor m_processor = new ProtocolProcessor();
|
private final ProtocolProcessor m_processor = new ProtocolProcessor();
|
||||||
@@ -75,7 +78,7 @@ public class ProtocolProcessorBootstrapper {
|
|||||||
m_mapStorage = new MapDBPersistentStore(props);
|
m_mapStorage = new MapDBPersistentStore(props);
|
||||||
m_mapStorage.initStore();
|
m_mapStorage.initStore();
|
||||||
IMessagesStore messagesStore = m_mapStorage.messagesStore();
|
IMessagesStore messagesStore = m_mapStorage.messagesStore();
|
||||||
ISessionsStore sessionsStore = m_mapStorage.sessionsStore();
|
ISessionsStore m_sessionsStore = m_mapStorage.sessionsStore();
|
||||||
|
|
||||||
List<InterceptHandler> observers = new ArrayList<>(embeddedObservers);
|
List<InterceptHandler> observers = new ArrayList<>(embeddedObservers);
|
||||||
String interceptorClassName = props.getProperty(BrokerConstants.INTERCEPT_HANDLER_PROPERTY_NAME);
|
String interceptorClassName = props.getProperty(BrokerConstants.INTERCEPT_HANDLER_PROPERTY_NAME);
|
||||||
@@ -95,7 +98,7 @@ public class ProtocolProcessorBootstrapper {
|
|||||||
}
|
}
|
||||||
m_interceptor = new BrokerInterceptor(observers);
|
m_interceptor = new BrokerInterceptor(observers);
|
||||||
|
|
||||||
subscriptions.init(sessionsStore);
|
subscriptions.init(m_sessionsStore);
|
||||||
|
|
||||||
String configPath = System.getProperty("moquette.path", null);
|
String configPath = System.getProperty("moquette.path", null);
|
||||||
String authenticatorClassName = props.getProperty(BrokerConstants.AUTHENTICATOR_CLASS_NAME, "");
|
String authenticatorClassName = props.getProperty(BrokerConstants.AUTHENTICATOR_CLASS_NAME, "");
|
||||||
@@ -140,7 +143,7 @@ public class ProtocolProcessorBootstrapper {
|
|||||||
|
|
||||||
boolean allowAnonymous = Boolean.parseBoolean(props.getProperty(BrokerConstants.ALLOW_ANONYMOUS_PROPERTY_NAME, "true"));
|
boolean allowAnonymous = Boolean.parseBoolean(props.getProperty(BrokerConstants.ALLOW_ANONYMOUS_PROPERTY_NAME, "true"));
|
||||||
boolean allowZeroByteClientId = Boolean.parseBoolean(props.getProperty(BrokerConstants.ALLOW_ZERO_BYTE_CLIENT_ID_PROPERTY_NAME, "false"));
|
boolean allowZeroByteClientId = Boolean.parseBoolean(props.getProperty(BrokerConstants.ALLOW_ZERO_BYTE_CLIENT_ID_PROPERTY_NAME, "false"));
|
||||||
m_processor.init(subscriptions, messagesStore, sessionsStore, authenticator, allowAnonymous, allowZeroByteClientId, authorizator, m_interceptor, props.getProperty(BrokerConstants.PORT_PROPERTY_NAME));
|
m_processor.init(subscriptions, messagesStore, m_sessionsStore, authenticator, allowAnonymous, allowZeroByteClientId, authorizator, m_interceptor, props.getProperty(BrokerConstants.PORT_PROPERTY_NAME));
|
||||||
return m_processor;
|
return m_processor;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -191,6 +194,10 @@ public class ProtocolProcessorBootstrapper {
|
|||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<Subscription> getSubscriptions() {
|
||||||
|
return m_sessionsStore.getSubscriptions();
|
||||||
|
}
|
||||||
|
|
||||||
public void shutdown() {
|
public void shutdown() {
|
||||||
this.m_mapStorage.close();
|
this.m_mapStorage.close();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -117,6 +117,16 @@ class MapDBSessionsStore implements ISessionsStore {
|
|||||||
return clientSubscriptions.get(couple.topicFilter);
|
return clientSubscriptions.get(couple.topicFilter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Subscription> getSubscriptions() {
|
||||||
|
List<Subscription> subscriptions = new ArrayList<>();
|
||||||
|
for (String clientID : m_persistentSessions.keySet()) {
|
||||||
|
ConcurrentMap<String, Subscription> clientSubscriptions = m_db.getHashMap("subscriptions_" + clientID);
|
||||||
|
subscriptions.addAll(clientSubscriptions.values());
|
||||||
|
}
|
||||||
|
return subscriptions;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean contains(String clientID) {
|
public boolean contains(String clientID) {
|
||||||
return m_db.exists("subscriptions_" + clientID);
|
return m_db.exists("subscriptions_" + clientID);
|
||||||
|
|||||||
@@ -97,6 +97,17 @@ public class ServerIntegrationEmbeddedPublishTest {
|
|||||||
m_server.internalPublish(message);
|
m_server.internalPublish(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void connectNoCleanSession() throws Exception {
|
||||||
|
MqttConnectOptions opts = new MqttConnectOptions();
|
||||||
|
opts.setCleanSession(false);
|
||||||
|
m_subscriber.connect(opts);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void subscribeToWithQosAndNoCleanSession(String topic, int qos) throws Exception {
|
||||||
|
connectNoCleanSession();
|
||||||
|
m_subscriber.subscribe(topic, qos);
|
||||||
|
}
|
||||||
|
|
||||||
private void verifyNoMessageIsReceived() throws Exception {
|
private void verifyNoMessageIsReceived() throws Exception {
|
||||||
MqttMessage msg = m_callback.getMessage(false);
|
MqttMessage msg = m_callback.getMessage(false);
|
||||||
assertNull(msg);
|
assertNull(msg);
|
||||||
@@ -276,4 +287,16 @@ public class ServerIntegrationEmbeddedPublishTest {
|
|||||||
MqttMessage message = m_callback.getMessage(true);
|
MqttMessage message = m_callback.getMessage(true);
|
||||||
assertTrue(message == null);
|
assertTrue(message == null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testClientSubscribeWithoutCleanSession() throws Exception {
|
||||||
|
LOG.info("*** testClientSubscribeWithoutCleanSession ***");
|
||||||
|
subscribeToWithQosAndNoCleanSession("foo", 1);
|
||||||
|
m_subscriber.disconnect();
|
||||||
|
assertTrue(m_server.getSubscriptions().size() == 1);
|
||||||
|
connectNoCleanSession();
|
||||||
|
assertTrue(m_server.getSubscriptions().size() == 1);
|
||||||
|
internalPublishToWithQosAndRetained("foo", QOSType.MOST_ONE, false);
|
||||||
|
verifyMessageIsReceivedSuccessfully();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -157,6 +157,15 @@ public class MemorySessionStore implements ISessionsStore {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Subscription> getSubscriptions() {
|
||||||
|
List<Subscription> subscriptions = new ArrayList<>();
|
||||||
|
for (Map.Entry<String, Set<Subscription>> entry : m_persistentSubscriptions.entrySet()) {
|
||||||
|
subscriptions.addAll(entry.getValue());
|
||||||
|
}
|
||||||
|
return subscriptions;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void inFlightAck(String clientID, int messageID) {
|
public void inFlightAck(String clientID, int messageID) {
|
||||||
Map<Integer, MessageGUID> m = this.m_inflightStore.get(clientID);
|
Map<Integer, MessageGUID> m = this.m_inflightStore.get(clientID);
|
||||||
|
|||||||
Reference in New Issue
Block a user