Fix issue #30 rewind of message ByteBuffer

This commit is contained in:
andrea
2014-02-15 12:06:03 +01:00
parent 5163b094ae
commit e73a2a8b9e
4 changed files with 112 additions and 10 deletions
@@ -245,15 +245,15 @@ class ProtocolProcessor implements EventHandler<ValueEvent> {
* */
private void publish2Subscribers(String topic, AbstractMessage.QOSType qos, ByteBuffer message, boolean retain, Integer messageID) {
LOG.debug("publish2Subscribers republishing to existing subscribers that matches the topic {}, content", topic);
LOG.debug("content <{}>", new String(message.array()));
if (LOG.isDebugEnabled()) {
LOG.debug("content <{}>", DebugUtils.payload2Str(message));
LOG.debug("subscription tree {}", subscriptions.dumpTree());
}
for (final Subscription sub : subscriptions.matches(topic)) {
if (qos.ordinal() > sub.getRequestedQos().ordinal()) {
qos = sub.getRequestedQos();
}
message.rewind();
LOG.debug("Broker republishing to client <{}> topic <{}> qos <{}>, active {}",
sub.getClientId(), sub.getTopic(), qos, sub.isActive());
@@ -298,7 +298,9 @@ class ProtocolProcessor implements EventHandler<ValueEvent> {
pubMessage.setPayload(message);
LOG.info("send publish message to <{}> on topic <{}>", clientId, topic);
LOG.debug("content <{}>", new String(message.array()));
if (LOG.isDebugEnabled()) {
LOG.debug("content <{}>", DebugUtils.payload2Str(message));
}
if (pubMessage.getQos() != AbstractMessage.QOSType.MOST_ONE) {
pubMessage.setMessageID(messageID);
}
@@ -22,7 +22,6 @@ import org.dna.mqtt.moquette.server.ServerChannel;
import static org.junit.Assert.*;
import static org.mockito.Mockito.*;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
/**
@@ -31,6 +30,7 @@ import org.junit.Test;
*/
public class ProtocolProcessorTest {
final static String FAKE_CLIENT_ID = "FAKE_123";
final static String FAKE_CLIENT_ID2 = "FAKE_456";
final static String FAKE_PUBLISHER_ID = "Publisher";
final static String FAKE_TOPIC = "/news";
@@ -76,6 +76,45 @@ public class ProtocolProcessorTest {
}
class MockReceiverChannel implements ServerChannel {
// byte m_returnCode;
AbstractMessage m_receivedMessage;
private Map<Object, Object> m_attributes = new HashMap<Object, Object>();
public Object getAttribute(Object key) {
return m_attributes.get(key);
}
public void setAttribute(Object key, Object value) {
m_attributes.put(key, value);
}
public void setIdleTime(int idleTime) {
}
public void close(boolean immediately) {
}
public AbstractMessage getMessage() {
return this.m_receivedMessage;
}
// public byte getReturnCode() {
// return this.m_returnCode;
// }
public void write(Object value) {
try {
this.m_receivedMessage = (AbstractMessage) value;
// if (this.m_receivedMessage instanceof PublishMessage) {
// T buf = (T) this.m_receivedMessage;
// }
} catch (Exception ex) {
throw new AssertionError("Wrong return code");
}
}
}
@Before
public void setUp() throws InterruptedException {
connMsg = new ConnectMessage();
@@ -151,8 +190,6 @@ public class ProtocolProcessorTest {
throw new IllegalArgumentException("Expected " + FAKE_TOPIC + " buf found " + topic);
}
}
};
//simulate a connect that register a clientID to an IoSession
@@ -175,6 +212,62 @@ public class ProtocolProcessorTest {
//TODO check received message attributes
}
@Test
public void testPublishToMultipleSubscribers() throws InterruptedException {
final Subscription subscription = new Subscription(FAKE_CLIENT_ID,
FAKE_TOPIC, AbstractMessage.QOSType.MOST_ONE, true);
final Subscription subscriptionClient2 = new Subscription(FAKE_CLIENT_ID2,
FAKE_TOPIC, AbstractMessage.QOSType.MOST_ONE, true);
//subscriptions.matches(topic) redefine the method to return true
SubscriptionsStore subs = new SubscriptionsStore() {
@Override
public List<Subscription> matches(String topic) {
if (topic.equals(FAKE_TOPIC)) {
return Arrays.asList(subscription, subscriptionClient2);
} else {
throw new IllegalArgumentException("Expected " + FAKE_TOPIC + " buf found " + topic);
}
}
};
//simulate a connect that register a clientID to an IoSession
subs.init(m_storageService);
m_processor.init(subs, m_storageService);
MockReceiverChannel firstReceiverSession = new MockReceiverChannel();
ConnectMessage connectMessage = new ConnectMessage();
connectMessage.setProcotolVersion((byte)3);
connectMessage.setClientID(FAKE_CLIENT_ID);
connectMessage.setCleanSession(subscription.isCleanSession());
m_processor.processConnect(firstReceiverSession, connectMessage);
//connect the second fake subscriber
MockReceiverChannel secondReceiverSession = new MockReceiverChannel();
ConnectMessage connectMessage2 = new ConnectMessage();
connectMessage2.setProcotolVersion((byte)3);
connectMessage2.setClientID(FAKE_CLIENT_ID2);
connectMessage2.setCleanSession(subscription.isCleanSession());
m_processor.processConnect(secondReceiverSession, connectMessage2);
//Exercise
ByteBuffer buffer = ByteBuffer.allocate(5).put("Hello".getBytes());
PublishEvent pubEvt = new PublishEvent(FAKE_TOPIC, AbstractMessage.QOSType.MOST_ONE, buffer, false, "FakeCLI", null);
m_processor.processPublish(pubEvt);
//Verify
Thread.sleep(100); //ugly but we dependend on the asynch that pull data from back disruptor
PublishMessage pub2FirstSubscriber = (PublishMessage) firstReceiverSession.getMessage();
assertNotNull(pub2FirstSubscriber);
String firstMessageContent = DebugUtils.payload2Str(pub2FirstSubscriber.getPayload());
assertEquals("Hello", firstMessageContent);
PublishMessage pub2SecondSubscriber = (PublishMessage) secondReceiverSession.getMessage();
assertNotNull(pub2SecondSubscriber);
String secondMessageContent = DebugUtils.payload2Str(pub2SecondSubscriber.getPayload());
assertEquals("Hello", secondMessageContent);
}
@Test
public void testSubscribe() {
//Exercise
+2 -2
View File
@@ -17,7 +17,7 @@ MqttMessage message = new MqttMessage('Hello world!!'.bytes)
message.setQos(0)
print "publishing.."
long startTime = System.currentTimeMillis()
(1..100000).each {
(1..10).each {
client.publish('topic', 'Hello world!!'.bytes, 0, false)
}
client.publish('/exit', 'Exit'.bytes, 0, false)
@@ -25,4 +25,4 @@ long stopTime = System.currentTimeMillis()
long spentTime = stopTime -startTime
println "published in ${spentTime} ms"
client.disconnect()
println "disconnected"
println "disconnected"
+9 -2
View File
@@ -11,7 +11,6 @@ import java.util.concurrent.CountDownLatch
import java.util.concurrent.TimeUnit
class SubscriberCallback implements MqttCallback {
int m_numReceived = 0
@@ -42,6 +41,7 @@ class SubscriberCallback implements MqttCallback {
client.disconnect()
m_latch.countDown()
} else {
println "-received ${message} on ${topic} with QoS ${message.qos}"
m_numReceived++
}
}
@@ -51,11 +51,18 @@ class SubscriberCallback implements MqttCallback {
}
}
if (args.size() < 2) {
println "Usage subscriber <host> <QoS>"
return
}
String host = args[0]
int qos = args[1] as int
String tmpDir = System.getProperty("java.io.tmpdir")
MqttDefaultFilePersistence dataStore = new MqttDefaultFilePersistence(tmpDir)
MqttClient client = new MqttClient("tcp://${host}:1883", "SubscriberClient", dataStore)
int rnd = (Math.random() * 100) as int
MqttClient client = new MqttClient("tcp://${host}:1883", "SubscriberClient${rnd}", dataStore)
def callback = new SubscriberCallback()
client.callback = callback
client.connect()