Fixed bug due to not persisted subscriptions into the store, on restart there were ghosts subscriptions that produced errors

This commit is contained in:
selva.andre
2014-09-19 22:00:51 +02:00
parent cc45b87ebe
commit 0940ac84a0
11 changed files with 124 additions and 42 deletions
@@ -16,6 +16,8 @@
package org.dna.mqtt.moquette.messaging.spi;
import java.util.List;
import java.util.Set;
import org.dna.mqtt.moquette.messaging.spi.impl.subscriptions.Subscription;
/**
@@ -35,6 +37,11 @@ public interface ISessionsStore {
*/
void wipeSubscriptions(String sessionID);
/**
* Updates the subscriptions set for the clientID
* */
void updateSubscriptions(String clientID, Set<Subscription> subscriptions);
List<Subscription> listAllSubscriptions();
/**
@@ -142,7 +142,12 @@ public class MemoryStorageService implements IMessagesStore, ISessionsStore {
public void wipeSubscriptions(String clientID) {
m_persistentSubscriptions.remove(clientID);
}
@Override
public void updateSubscriptions(String clientID, Set<Subscription> subscriptions) {
m_persistentSubscriptions.put(clientID, subscriptions);
}
@Override
public boolean contains(String clientID) {
return m_persistentSubscriptions.containsKey(clientID);
@@ -19,7 +19,6 @@ import com.lmax.disruptor.EventHandler;
import com.lmax.disruptor.RingBuffer;
import com.lmax.disruptor.dsl.Disruptor;
import java.util.List;
import java.util.Properties;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
@@ -30,7 +29,6 @@ import org.dna.mqtt.moquette.messaging.spi.IMessaging;
import org.dna.mqtt.moquette.messaging.spi.ISessionsStore;
import org.dna.mqtt.moquette.messaging.spi.IMessagesStore;
import org.dna.mqtt.moquette.messaging.spi.impl.events.*;
import org.dna.mqtt.moquette.messaging.spi.impl.subscriptions.Subscription;
import org.dna.mqtt.moquette.messaging.spi.impl.subscriptions.SubscriptionsStore;
import org.dna.mqtt.moquette.messaging.spi.persistence.MapDBPersistentStore;
import org.dna.mqtt.moquette.proto.messages.*;
@@ -61,6 +59,7 @@ public class SimpleMessaging implements IMessaging, EventHandler<ValueEvent> {
private ISessionsStore m_sessionsStore;
private ExecutorService m_executor;
private Disruptor<ValueEvent> m_disruptor;
private static SimpleMessaging INSTANCE;
@@ -82,14 +81,14 @@ public class SimpleMessaging implements IMessaging, EventHandler<ValueEvent> {
public void init(Properties configProps) {
subscriptions = new SubscriptionsStore();
m_executor = Executors.newFixedThreadPool(1);
Disruptor<ValueEvent> disruptor = new Disruptor<ValueEvent>(ValueEvent.EVENT_FACTORY, 1024 * 32, m_executor);
/*Disruptor<ValueEvent> disruptor = new Disruptor<ValueEvent>(ValueEvent.EVENT_FACTORY, 1024 * 32, m_executor,
m_disruptor = new Disruptor<ValueEvent>(ValueEvent.EVENT_FACTORY, 1024 * 32, m_executor);
/*Disruptor<ValueEvent> m_disruptor = new Disruptor<ValueEvent>(ValueEvent.EVENT_FACTORY, 1024 * 32, m_executor,
ProducerType.MULTI, new BusySpinWaitStrategy());*/
disruptor.handleEventsWith(this);
disruptor.start();
m_disruptor.handleEventsWith(this);
m_disruptor.start();
// Get the ring buffer from the Disruptor to be used for publishing.
m_ringBuffer = disruptor.getRingBuffer();
m_ringBuffer = m_disruptor.getRingBuffer();
annotationSupport.processAnnotations(m_processor);
processInit(configProps);
@@ -127,6 +126,7 @@ public class SimpleMessaging implements IMessaging, EventHandler<ValueEvent> {
boolean elapsed = !m_stopLatch.await(10, TimeUnit.SECONDS);
LOG.debug("after m_stopLatch");
m_executor.shutdown();
m_disruptor.shutdown();
if (elapsed) {
LOG.error("Can't stop the server in 10 seconds");
}
@@ -164,8 +164,9 @@ public class SimpleMessaging implements IMessaging, EventHandler<ValueEvent> {
m_storageService.initStore();
List<Subscription> storedSubscriptions = m_sessionsStore.listAllSubscriptions();
subscriptions.init(storedSubscriptions);
//List<Subscription> storedSubscriptions = m_sessionsStore.listAllSubscriptions();
//subscriptions.init(storedSubscriptions);
subscriptions.init(m_sessionsStore);
String passwdPath = props.getProperty("password_file", "");
String configPath = System.getProperty("moquette.path", null);
@@ -16,12 +16,10 @@
package org.dna.mqtt.moquette.messaging.spi.impl.subscriptions;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Queue;
import java.util.*;
import java.util.concurrent.LinkedBlockingDeque;
import org.dna.mqtt.moquette.messaging.spi.ISessionsStore;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -31,7 +29,7 @@ import org.slf4j.LoggerFactory;
* @author andrea
*/
public class SubscriptionsStore {
public static interface IVisitor<T> {
void visit(TreeNode node);
@@ -70,19 +68,21 @@ public class SubscriptionsStore {
}
private TreeNode subscriptions = new TreeNode(null);
private ISessionsStore m_sessionsStore;
private static final Logger LOG = LoggerFactory.getLogger(SubscriptionsStore.class);
/**
* Initialize the subscription tree with the list of subscriptions.
*/
public void init(List<Subscription> subscriptions) {
public void init(ISessionsStore sessionsStore) {
LOG.debug("init invoked");
m_sessionsStore = sessionsStore;
List<Subscription> subscriptions = sessionsStore.listAllSubscriptions();
//reload any subscriptions persisted
if (LOG.isDebugEnabled()) {
LOG.debug("Reloading all stored subscriptions...subscription tree before {}", dumpTree());
}
for (Subscription subscription : subscriptions) {
LOG.debug("Re-subscribing {} to topic {}", subscription.getClientId(), subscription.getTopicFilter());
addDirect(subscription);
@@ -169,18 +169,24 @@ public class SubscriptionsStore {
*/
public void removeForClient(String clientID) {
subscriptions.removeClientSubscriptions(clientID);
//TODO persist the update
//remove from log all subscriptions
// m_storageService.removeAllSubscriptions(clientID);
}
public void deactivate(String clientID) {
subscriptions.deactivate(clientID);
//persist the update
Set<Subscription> subs = subscriptions.findAllByClientID(clientID);
m_sessionsStore.updateSubscriptions(clientID, subs);
}
public void activate(String clientID) {
LOG.debug("Activating subscriptions for clientID <{}>", clientID);
subscriptions.activate(clientID);
//persist the update
Set<Subscription> subs = subscriptions.findAllByClientID(clientID);
m_sessionsStore.updateSubscriptions(clientID, subs);
}
/**
@@ -15,15 +15,11 @@
*/
package org.dna.mqtt.moquette.messaging.spi.impl.subscriptions;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Queue;
import java.util.*;
import java.util.concurrent.LinkedBlockingQueue;
class TreeNode {
private class ClientIDComparator implements Comparator<Subscription> {
public int compare(Subscription o1, Subscription o2) {
@@ -181,6 +177,22 @@ class TreeNode {
for (TreeNode child : m_children) {
child.activate(clientID);
}
}
/**
* @return the set of subscriptions for the given client.
* */
Set<Subscription> findAllByClientID(String clientID) {
Set<Subscription> subs = new HashSet<Subscription>();
for (Subscription s : m_subscriptions) {
if (s.clientId.equals(clientID)) {
subs.add(s);
}
}
//go deep
for (TreeNode child : m_children) {
subs.addAll(child.findAllByClientID(clientID));
}
return subs;
}
}
@@ -203,6 +203,12 @@ public class MapDBPersistentStore implements IMessagesStore, ISessionsStore {
m_db.commit();
}
@Override
public void updateSubscriptions(String clientID, Set<Subscription> subscriptions) {
m_persistentSubscriptions.put(clientID, subscriptions);
m_db.commit();
}
public List<Subscription> listAllSubscriptions() {
List<Subscription> allSubscriptions = new ArrayList<Subscription>();
for (Map.Entry<String, Set<Subscription>> entry : m_persistentSubscriptions.entrySet()) {
@@ -219,6 +225,7 @@ public class MapDBPersistentStore implements IMessagesStore, ISessionsStore {
public void close() {
this.m_db.commit();
LOG.debug("persisted subscriptions {}", m_persistentSubscriptions);
this.m_db.close();
LOG.debug("closed disk storage");
}