Updated publish message parto to conform to 3.1.1 specification

This commit is contained in:
selva.andre
2014-07-31 00:08:41 +02:00
parent 482ffe0c65
commit d4ef81a7ef
9 changed files with 160 additions and 18 deletions
@@ -68,4 +68,6 @@ public interface IMessagesStore {
void removeQoS2Message(String publishKey);
PublishEvent retrieveQoS2Message(String publishKey);
void cleanRetained(String topic);
}
@@ -150,6 +150,11 @@ public class HawtDBPersistentStore implements IMessagesStore, ISessionsStore {
m_qos2Store = (SortedIndex<String, StoredPublishEvent>) m_multiIndexFactory.openOrCreate("qos2Store", indexFactory);
}
@Override
public void cleanRetained(String topic) {
m_retainedStore.remove(topic);
}
@Override
public void storeRetained(String topic, ByteBuffer message, AbstractMessage.QOSType qos) {
if (!message.hasRemaining()) {
@@ -47,9 +47,14 @@ public class MemoryStorageService implements IMessagesStore, ISessionsStore {
private static final Logger LOG = LoggerFactory.getLogger(MemoryStorageService.class);
public void initStore() {
//To change body of implemented methods use File | Settings | File Templates.
}
@Override
public void cleanRetained(String topic) {
m_retainedStore.remove(topic);
}
@Override
public void storeRetained(String topic, ByteBuffer message, AbstractMessage.QOSType qos) {
if (!message.hasRemaining()) {
//clean the message from topic
@@ -62,6 +67,7 @@ public class MemoryStorageService implements IMessagesStore, ISessionsStore {
}
}
@Override
public Collection<HawtDBPersistentStore.StoredMessage> searchMatching(IMatchingCondition condition) {
LOG.debug("searchMatching scanning all retained messages, presents are {}", m_retainedStore.size());
@@ -77,6 +83,7 @@ public class MemoryStorageService implements IMessagesStore, ISessionsStore {
return results;
}
@Override
public void storePublishForFuture(PublishEvent evt) {
LOG.debug("storePublishForFuture store evt {}", evt);
List<PublishEvent> storedEvents;
@@ -95,6 +102,7 @@ public class MemoryStorageService implements IMessagesStore, ISessionsStore {
return m_persistentMessageStore.get(clientID);
}
@Override
public void cleanPersistedPublishMessage(String clientID, int messageID) {
List<PublishEvent> events = m_persistentMessageStore.get(clientID);
PublishEvent toRemoveEvt = null;
@@ -107,18 +115,22 @@ public class MemoryStorageService implements IMessagesStore, ISessionsStore {
m_persistentMessageStore.put(clientID, events);
}
@Override
public void cleanPersistedPublishes(String clientID) {
m_persistentMessageStore.remove(clientID);
}
@Override
public void cleanInFlight(String msgID) {
m_inflightStore.remove(msgID);
}
@Override
public void addInFlight(PublishEvent evt, String publishKey) {
m_inflightStore.put(publishKey, evt);
}
@Override
public void addNewSubscription(Subscription newSubscription, String clientID) {
if (!m_persistentSubscriptions.containsKey(clientID)) {
m_persistentSubscriptions.put(clientID, new HashSet<Subscription>());
@@ -131,6 +143,7 @@ public class MemoryStorageService implements IMessagesStore, ISessionsStore {
}
}
@Override
public void wipeSubscriptions(String clientID) {
m_persistentSubscriptions.remove(clientID);
}
@@ -140,6 +153,7 @@ public class MemoryStorageService implements IMessagesStore, ISessionsStore {
return m_persistentSubscriptions.containsKey(clientID);
}
@Override
public List<Subscription> listAllSubscriptions() {
List<Subscription> allSubscriptions = new ArrayList<Subscription>();
for (Map.Entry<String, Set<Subscription>> entry : m_persistentSubscriptions.entrySet()) {
@@ -148,19 +162,23 @@ public class MemoryStorageService implements IMessagesStore, ISessionsStore {
return allSubscriptions;
}
@Override
public void close() {
//To change body of implemented methods use File | Settings | File Templates.
}
@Override
public void persistQoS2Message(String publishKey, PublishEvent evt) {
LOG.debug("persistQoS2Message store pubKey {}, evt {}", publishKey, evt);
m_qos2Store.put(publishKey, evt);
}
@Override
public void removeQoS2Message(String publishKey) {
m_qos2Store.remove(publishKey);
}
@Override
public PublishEvent retrieveQoS2Message(String publishKey) {
return m_qos2Store.get(publishKey);
}
@@ -303,7 +303,12 @@ class ProtocolProcessor implements EventHandler<ValueEvent> {
}
if (retain) {
m_messagesStore.storeRetained(topic, message, qos);
if (qos == AbstractMessage.QOSType.MOST_ONE) {
//QoS == 0 && retain => clean old retained
m_messagesStore.cleanRetained(topic);
} else {
m_messagesStore.storeRetained(topic, message, qos);
}
}
}
@@ -408,7 +413,7 @@ class ProtocolProcessor implements EventHandler<ValueEvent> {
}
LOG.debug("clientIDs are {}", m_clientIDs);
if (m_clientIDs.get(clientId) == null) {
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 ConnectionDescriptor for client %s in cache %s", clientId, m_clientIDs));
}
// LOG.debug("Session for clientId " + clientId + " is " + m_clientIDs.get(clientId).getSession());
// m_clientIDs.get(clientId).getSession().write(pubAckMessage);
@@ -17,12 +17,14 @@ package org.dna.mqtt.moquette.messaging.spi.impl;
import java.nio.ByteBuffer;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import org.dna.mqtt.moquette.messaging.spi.IMatchingCondition;
import org.dna.mqtt.moquette.messaging.spi.IMessagesStore;
import org.dna.mqtt.moquette.messaging.spi.ISessionsStore;
import org.dna.mqtt.moquette.messaging.spi.impl.events.PublishEvent;
@@ -41,6 +43,7 @@ import org.dna.mqtt.moquette.server.ServerChannel;
import static org.junit.Assert.*;
import org.junit.Before;
import org.junit.Test;
import static org.junit.internal.runners.model.MultipleFailureException.assertEmpty;
import static org.mockito.Mockito.*;
/**
@@ -506,4 +509,31 @@ public class ProtocolProcessorTest {
//Verify no message is received
assertNull(m_receivedMessage);
}
/**
* Verify that receiving a publish with retained message and with Q0S = 0
* clean the existing retained messages for that topic.
*/
@Test
public void testCleanRetainedStoreAfterAQoS0AndRetainedTrue() {
//prepare and existing retained store
ByteBuffer payload = ByteBuffer.allocate(5).put("Hello".getBytes());
PublishEvent pubEvt = new PublishEvent(FAKE_TOPIC, AbstractMessage.QOSType.LEAST_ONE, payload, true, "Publisher");
m_processor.processPublish(pubEvt);
//Exercise
PublishEvent cleanPubEvt = new PublishEvent(FAKE_TOPIC, AbstractMessage.QOSType.MOST_ONE, payload, true, "Publisher");
m_processor.processPublish(cleanPubEvt);
//Verify
// List<PublishEvent> retainedPublishes = m_storageService.retrievePersistedPublishes("Publisher");
Collection<HawtDBPersistentStore.StoredMessage> messages = m_storageService.searchMatching(new IMatchingCondition() {
public boolean match(String key) {
return SubscriptionsStore.matchTopics(key, FAKE_TOPIC);
}
});
assertTrue(messages.isEmpty());
}
}
@@ -172,7 +172,7 @@ public class ServerIntegrationPahoTest {
public void testRetain_maintainMessage_againstClientDestruction() throws Exception {
LOG.info("*** testRetain_maintainMessage_againstClientDestruction ***");
m_client.connect();
m_client.publish("/topic", "Test my payload".getBytes(), 0, true);
m_client.publish("/topic", "Test my payload".getBytes(), 1, true);
m_client.disconnect();