Work toward ONOS-1451: Separate Event Key space per instance

Misc changes and cleanup (Step 3):

* Enabled the usage of ONOS Instance ID inside class TopologyEvent
  - Added the ONOS Instance ID as part of the TopologyEvent key
  - Use the ONOS Instance ID inside method toString() and equals()
  - Also, added new method TopologyEvent.getIDasByteBuffer()

* Added support for Mastership Events inside class TopologyEvents,
  including the JSON output.
  NOTE: For now the JSON output for the Topology object itself doesn't
  contain the corresponding Mastership info. The need for
  adding such info is TBD.

* Added new class TopologyEventFilter that will perform the filtering
  if incoming events. For now the internal logic of this filter is empty.

* Reordered some of the MastershipEvent-related code right before the
  SwitchEvent-related code so it is more consistent.

Change-Id: I940c4686b776f5136a10c25bc49278b69c548fc5
diff --git a/src/main/java/net/onrc/onos/core/topology/TopologyDiscoveryInterface.java b/src/main/java/net/onrc/onos/core/topology/TopologyDiscoveryInterface.java
index 289ed05..c373bad 100644
--- a/src/main/java/net/onrc/onos/core/topology/TopologyDiscoveryInterface.java
+++ b/src/main/java/net/onrc/onos/core/topology/TopologyDiscoveryInterface.java
@@ -8,6 +8,20 @@
  */
 public interface TopologyDiscoveryInterface {
     /**
+     * Switch Mastership updated event.
+     *
+     * @param mastershipEvent the mastership event.
+     */
+    public void putSwitchMastershipEvent(MastershipEvent mastershipEvent);
+
+    /**
+     * Switch Mastership removed event.
+     *
+     * @param mastershipEvent the mastership event.
+     */
+    public void removeSwitchMastershipEvent(MastershipEvent mastershipEvent);
+
+    /**
      * Switch discovered event.
      *
      * @param switchEvent the switch event.
@@ -64,18 +78,4 @@
      * @param hostEvent the host event.
      */
     public void removeHostDiscoveryEvent(HostEvent hostEvent);
-
-    /**
-     * Switch Mastership updated event.
-     *
-     * @param mastershipEvent the mastership event.
-     */
-    public void putSwitchMastershipEvent(MastershipEvent mastershipEvent);
-
-    /**
-     * Switch Mastership removed event.
-     *
-     * @param mastershipEvent the mastership event.
-     */
-    public void removeSwitchMastershipEvent(MastershipEvent mastershipEvent);
 }
diff --git a/src/main/java/net/onrc/onos/core/topology/TopologyEvent.java b/src/main/java/net/onrc/onos/core/topology/TopologyEvent.java
index df38b5e..4ea9e31 100644
--- a/src/main/java/net/onrc/onos/core/topology/TopologyEvent.java
+++ b/src/main/java/net/onrc/onos/core/topology/TopologyEvent.java
@@ -1,5 +1,7 @@
 package net.onrc.onos.core.topology;
 
+import java.nio.ByteBuffer;
+import java.nio.charset.StandardCharsets;
 import java.util.Objects;
 
 import net.onrc.onos.core.util.OnosInstanceId;
@@ -10,17 +12,17 @@
  * Self-contained Topology event Object
  * <p/>
  * TODO: For now the topology event contains one of the following events:
- * Switch, Port, Link, Host, Switch Mastership. In the future it will contain
+ * Switch Mastership, Switch, Port, Link, Host. In the future it will contain
  * multiple events in a single transaction.
  * TODO: This class should become immutable after its internals and usage
  * are finalized.
  */
 public final class TopologyEvent {
+    private final MastershipEvent mastershipEvent; // Set for Mastership event
     private final SwitchEvent switchEvent;      // Set for Switch event
     private final PortEvent portEvent;          // Set for Port event
     private final LinkEvent linkEvent;          // Set for Link event
     private final HostEvent hostEvent;          // Set for Host event
-    private final MastershipEvent mastershipEvent; // Set for Mastership event
     private final OnosInstanceId onosInstanceId;   // The ONOS Instance ID
 
     /**
@@ -28,75 +30,15 @@
      */
     @Deprecated
     protected TopologyEvent() {
+        mastershipEvent = null;
         switchEvent = null;
         portEvent = null;
         linkEvent = null;
         hostEvent = null;
-        mastershipEvent = null;
         onosInstanceId = null;
     }
 
     /**
-     * Constructor for given Switch event.
-     *
-     * @param switchEvent the Switch event to use.
-     * @param onosInstanceId the ONOS Instance ID that originates the event.
-     */
-    TopologyEvent(SwitchEvent switchEvent, OnosInstanceId onosInstanceId) {
-        this.switchEvent = checkNotNull(switchEvent);
-        this.portEvent = null;
-        this.linkEvent = null;
-        this.hostEvent = null;
-        this.mastershipEvent = null;
-        this.onosInstanceId = checkNotNull(onosInstanceId);
-    }
-
-    /**
-     * Constructor for given Port event.
-     *
-     * @param portEvent the Port event to use.
-     * @param onosInstanceId the ONOS Instance ID that originates the event.
-     */
-    TopologyEvent(PortEvent portEvent, OnosInstanceId onosInstanceId) {
-        this.switchEvent = null;
-        this.portEvent = checkNotNull(portEvent);
-        this.linkEvent = null;
-        this.hostEvent = null;
-        this.mastershipEvent = null;
-        this.onosInstanceId = checkNotNull(onosInstanceId);
-    }
-
-    /**
-     * Constructor for given Link event.
-     *
-     * @param linkEvent the Link event to use.
-     * @param onosInstanceId the ONOS Instance ID that originates the event.
-     */
-    TopologyEvent(LinkEvent linkEvent, OnosInstanceId onosInstanceId) {
-        this.switchEvent = null;
-        this.portEvent = null;
-        this.linkEvent = checkNotNull(linkEvent);
-        this.hostEvent = null;
-        this.mastershipEvent = null;
-        this.onosInstanceId = checkNotNull(onosInstanceId);
-    }
-
-    /**
-     * Constructor for given Host event.
-     *
-     * @param hostEvent the Host event to use.
-     * @param onosInstanceId the ONOS Instance ID that originates the event.
-     */
-    TopologyEvent(HostEvent hostEvent, OnosInstanceId onosInstanceId) {
-        this.switchEvent = null;
-        this.portEvent = null;
-        this.linkEvent = null;
-        this.hostEvent = checkNotNull(hostEvent);
-        this.mastershipEvent = null;
-        this.onosInstanceId = checkNotNull(onosInstanceId);
-    }
-
-    /**
      * Constructor for given Switch Mastership event.
      *
      * @param mastershipEvent the Switch Mastership event to use.
@@ -104,15 +46,84 @@
      */
     TopologyEvent(MastershipEvent mastershipEvent,
                   OnosInstanceId onosInstanceId) {
+        this.mastershipEvent = checkNotNull(mastershipEvent);
         this.switchEvent = null;
         this.portEvent = null;
         this.linkEvent = null;
         this.hostEvent = null;
-        this.mastershipEvent = checkNotNull(mastershipEvent);
         this.onosInstanceId = checkNotNull(onosInstanceId);
     }
 
     /**
+     * Constructor for given Switch event.
+     *
+     * @param switchEvent the Switch event to use.
+     * @param onosInstanceId the ONOS Instance ID that originates the event.
+     */
+    TopologyEvent(SwitchEvent switchEvent, OnosInstanceId onosInstanceId) {
+        this.mastershipEvent = null;
+        this.switchEvent = checkNotNull(switchEvent);
+        this.portEvent = null;
+        this.linkEvent = null;
+        this.hostEvent = null;
+        this.onosInstanceId = checkNotNull(onosInstanceId);
+    }
+
+    /**
+     * Constructor for given Port event.
+     *
+     * @param portEvent the Port event to use.
+     * @param onosInstanceId the ONOS Instance ID that originates the event.
+     */
+    TopologyEvent(PortEvent portEvent, OnosInstanceId onosInstanceId) {
+        this.mastershipEvent = null;
+        this.switchEvent = null;
+        this.portEvent = checkNotNull(portEvent);
+        this.linkEvent = null;
+        this.hostEvent = null;
+        this.onosInstanceId = checkNotNull(onosInstanceId);
+    }
+
+    /**
+     * Constructor for given Link event.
+     *
+     * @param linkEvent the Link event to use.
+     * @param onosInstanceId the ONOS Instance ID that originates the event.
+     */
+    TopologyEvent(LinkEvent linkEvent, OnosInstanceId onosInstanceId) {
+        this.mastershipEvent = null;
+        this.switchEvent = null;
+        this.portEvent = null;
+        this.linkEvent = checkNotNull(linkEvent);
+        this.hostEvent = null;
+        this.onosInstanceId = checkNotNull(onosInstanceId);
+    }
+
+    /**
+     * Constructor for given Host event.
+     *
+     * @param hostEvent the Host event to use.
+     * @param onosInstanceId the ONOS Instance ID that originates the event.
+     */
+    TopologyEvent(HostEvent hostEvent, OnosInstanceId onosInstanceId) {
+        this.mastershipEvent = null;
+        this.switchEvent = null;
+        this.portEvent = null;
+        this.linkEvent = null;
+        this.hostEvent = checkNotNull(hostEvent);
+        this.onosInstanceId = checkNotNull(onosInstanceId);
+    }
+
+    /**
+     * Gets the Mastership event.
+     *
+     * @return the Mastership event.
+     */
+    public MastershipEvent getMastershipEvent() {
+        return mastershipEvent;
+    }
+
+    /**
      * Gets the Switch event.
      *
      * @return the Switch event.
@@ -149,16 +160,16 @@
     }
 
     /**
-     * Gets the Mastership event.
+     * Gets the ONOS Instance ID.
      *
-     * @return the Mastership event.
+     * @return the ONOS Instance ID.
      */
-    public MastershipEvent getMastershipEvent() {
-        return mastershipEvent;
+    public OnosInstanceId getOnosInstanceId() {
+        return onosInstanceId;
     }
 
     /**
-     * Check if all events contained are equal.
+     * Checks if all events contained are equal.
      *
      * @param obj TopologyEvent to compare against
      */
@@ -177,69 +188,118 @@
         }
 
         TopologyEvent other = (TopologyEvent) obj;
-        // TODO: For now the onosInstanceId is not used
-        return Objects.equals(switchEvent, other.switchEvent) &&
-                Objects.equals(portEvent, other.portEvent) &&
-                Objects.equals(linkEvent, other.linkEvent) &&
-                Objects.equals(hostEvent, other.hostEvent) &&
-                Objects.equals(mastershipEvent, other.mastershipEvent);
+        return Objects.equals(mastershipEvent, other.mastershipEvent) &&
+            Objects.equals(switchEvent, other.switchEvent) &&
+            Objects.equals(portEvent, other.portEvent) &&
+            Objects.equals(linkEvent, other.linkEvent) &&
+            Objects.equals(hostEvent, other.hostEvent) &&
+            Objects.equals(onosInstanceId, other.onosInstanceId);
     }
 
     @Override
     public int hashCode() {
-        // TODO: For now the onosInstanceId is not used
-        return Objects.hash(switchEvent, portEvent, linkEvent, hostEvent,
-                            mastershipEvent);
+        return Objects.hash(mastershipEvent, switchEvent, portEvent,
+                            linkEvent, hostEvent, onosInstanceId);
     }
 
     /**
-     * Get the string representation of the event.
+     * Gets the string representation of the event.
      *
      * @return the string representation of the event.
      */
     @Override
     public String toString() {
-        // TODO: For now the onosInstanceId is not used
-        if (switchEvent != null) {
-            return switchEvent.toString();
-        }
-        if (portEvent != null) {
-            return portEvent.toString();
-        }
-        if (linkEvent != null) {
-            return linkEvent.toString();
-        }
-        if (hostEvent != null) {
-            return hostEvent.toString();
-        }
-        if (mastershipEvent != null) {
-            return mastershipEvent.toString();
-        }
-        return "[Empty TopologyEvent]";
+        String eventStr = null;
+
+        //
+        // Get the Event string
+        //
+        do {
+            if (mastershipEvent != null) {
+                eventStr = mastershipEvent.toString();
+                break;
+            }
+            if (switchEvent != null) {
+                eventStr = switchEvent.toString();
+                break;
+            }
+            if (portEvent != null) {
+                eventStr = portEvent.toString();
+                break;
+            }
+            if (linkEvent != null) {
+                eventStr = linkEvent.toString();
+                break;
+            }
+            if (hostEvent != null) {
+                eventStr = hostEvent.toString();
+                break;
+            }
+            // No event found
+            return "[Empty TopologyEvent]";
+        } while (false);
+
+        return "[TopologyEvent " + eventStr + " from " +
+            onosInstanceId.toString() + "]";
     }
 
     /**
-     * Get the Topology event ID.
+     * Gets the Topology event ID as a byte array.
      *
-     * @return the Topology event ID.
+     * @return the Topology event ID as a byte array.
      */
     public byte[] getID() {
-        // TODO: For now the onosInstanceId is not used
-        if (switchEvent != null) {
-            return switchEvent.getID();
-        }
-        if (portEvent != null) {
-            return portEvent.getID();
-        }
-        if (linkEvent != null) {
-            return linkEvent.getID();
-        }
-        if (hostEvent != null) {
-            return hostEvent.getID();
-        }
-        if (mastershipEvent != null) {
-            return mastershipEvent.getID();
-        }
-        throw new IllegalStateException("Invalid TopologyEvent ID");
+        return getIDasByteBuffer().array();
+    }
+
+    /**
+     * Gets the Topology event ID as a ByteBuffer.
+     *
+     * @return the Topology event ID as a ByteBuffer.
+     */
+    public ByteBuffer getIDasByteBuffer() {
+        ByteBuffer eventId = null;
+
+        //
+        // Get the Event ID
+        //
+        do {
+            if (mastershipEvent != null) {
+                eventId = mastershipEvent.getIDasByteBuffer();
+                break;
+            }
+            if (switchEvent != null) {
+                eventId = switchEvent.getIDasByteBuffer();
+                break;
+            }
+            if (portEvent != null) {
+                eventId = portEvent.getIDasByteBuffer();
+                break;
+            }
+            if (linkEvent != null) {
+                eventId = linkEvent.getIDasByteBuffer();
+                break;
+            }
+            if (hostEvent != null) {
+                eventId = hostEvent.getIDasByteBuffer();
+                break;
+            }
+            // No event found
+            throw new IllegalStateException("Invalid TopologyEvent ID");
+        } while (false);
+
+        //
+        // Prepare the ONOS Instance ID. The '@' separator is needed to avoid
+        // potential key collisions.
+        //
+        byte[] onosId = ("@" + onosInstanceId.toString()).getBytes(StandardCharsets.UTF_8);
+
+        // Concatenate the IDs
+        ByteBuffer buf =
+            ByteBuffer.allocate(eventId.capacity() + onosId.length);
+        buf.put(eventId);
+        buf.put(onosId);
+        buf.flip();
+        return buf;
     }
 }
diff --git a/src/main/java/net/onrc/onos/core/topology/TopologyEventFilter.java b/src/main/java/net/onrc/onos/core/topology/TopologyEventFilter.java
new file mode 100644
index 0000000..65eed32
--- /dev/null
+++ b/src/main/java/net/onrc/onos/core/topology/TopologyEventFilter.java
@@ -0,0 +1,27 @@
+package net.onrc.onos.core.topology;
+
+import java.util.Collection;
+
+import net.onrc.onos.core.util.EventEntry;
+
+/**
+ * Stateful filter for filtering Topology events.
+ * <p/>
+ * NOTE: The filter itself keeps internal state about filtered events.
+ * As part of the filtering logic, a previously suppressed event might
+ * be genenerated (released) later because of some other event.
+ */
+public class TopologyEventFilter {
+    /**
+     * Filter a collection of events.
+     *
+     * @param events the events to filter.
+     * @return a collection of filtered events.
+     */
+    Collection<EventEntry<TopologyEvent>> filterEvents(
+                Collection<EventEntry<TopologyEvent>> events) {
+
+        // TODO: Not implemented yet
+        return events;
+    }
+}
diff --git a/src/main/java/net/onrc/onos/core/topology/TopologyEvents.java b/src/main/java/net/onrc/onos/core/topology/TopologyEvents.java
index 1de3caf..543c1cb 100644
--- a/src/main/java/net/onrc/onos/core/topology/TopologyEvents.java
+++ b/src/main/java/net/onrc/onos/core/topology/TopologyEvents.java
@@ -15,10 +15,10 @@
  * <p/>
  * (b) The processing order of the "removed" events should be:
  * removedHostEvents, removedLinkEvents, removedPortEvents,
- * removedSwitchEvents
+ * removedSwitchEvents, removedMastershipEvents
  * <p/>
  * (c) The processing order of the "added" events should be:
- * addedSwitchEvents, addedPortEvents, addedLinkEvents,
+ * addedMastershipEvents, addedSwitchEvents, addedPortEvents, addedLinkEvents,
  * addedHostEvents
  * <p/>
  * The above ordering guarantees that removing a port for example
@@ -30,6 +30,8 @@
  */
 @JsonSerialize(using = TopologyEventsSerializer.class)
 public final class TopologyEvents {
+    private final Collection<MastershipEvent> addedMastershipEvents;
+    private final Collection<MastershipEvent> removedMastershipEvents;
     private final Collection<SwitchEvent> addedSwitchEvents;
     private final Collection<SwitchEvent> removedSwitchEvents;
     private final Collection<PortEvent> addedPortEvents;
@@ -42,6 +44,8 @@
     /**
      * Constructor.
      *
+     * @param addedMastershipEvents the collection of added Mastership Events.
+     * @param removedMastershipEvents the collection of removed Mastership Events.
      * @param addedSwitchEvents the collection of added Switch Events.
      * @param removedSwitchEvents the collection of removed Switch Events.
      * @param addedPortEvents the collection of added Port Events.
@@ -52,7 +56,9 @@
      * @param removedHostEvents the collection of removed Host Events.
      */
     // CHECKSTYLE:OFF suppress the warning about too many parameters
-    public TopologyEvents(Collection<SwitchEvent> addedSwitchEvents,
+    public TopologyEvents(Collection<MastershipEvent> addedMastershipEvents,
+                          Collection<MastershipEvent> removedMastershipEvents,
+                          Collection<SwitchEvent> addedSwitchEvents,
                           Collection<SwitchEvent> removedSwitchEvents,
                           Collection<PortEvent> addedPortEvents,
                           Collection<PortEvent> removedPortEvents,
@@ -61,6 +67,10 @@
                           Collection<HostEvent> addedHostEvents,
                           Collection<HostEvent> removedHostEvents) {
         // CHECKSTYLE:ON
+        this.addedMastershipEvents =
+            Collections.unmodifiableCollection(addedMastershipEvents);
+        this.removedMastershipEvents =
+            Collections.unmodifiableCollection(removedMastershipEvents);
         this.addedSwitchEvents =
             Collections.unmodifiableCollection(addedSwitchEvents);
         this.removedSwitchEvents =
@@ -80,6 +90,24 @@
     }
 
     /**
+     * Gets the collection of added Mastership Events.
+     *
+     * @return the collection of added Mastership Events.
+     */
+    public Collection<MastershipEvent> getAddedMastershipEvents() {
+        return addedMastershipEvents;
+    }
+
+    /**
+     * Gets the collection of removed Mastership Events.
+     *
+     * @return the collection of removed Mastership Events.
+     */
+    public Collection<MastershipEvent> getRemovedMastershipEvents() {
+        return removedMastershipEvents;
+    }
+
+    /**
      * Gets the collection of added Switch Events.
      *
      * @return the collection of added Switch Events.
diff --git a/src/main/java/net/onrc/onos/core/topology/TopologyManager.java b/src/main/java/net/onrc/onos/core/topology/TopologyManager.java
index 10fa6be..05abc46 100644
--- a/src/main/java/net/onrc/onos/core/topology/TopologyManager.java
+++ b/src/main/java/net/onrc/onos/core/topology/TopologyManager.java
@@ -72,6 +72,7 @@
     private final IControllerRegistryService registryService;
     private CopyOnWriteArrayList<ITopologyListener> topologyListeners;
     private Kryo kryo = KryoFactory.newKryoObject();
+    private final TopologyEventFilter eventFilter = new TopologyEventFilter();
 
     //
     // Metrics
@@ -153,6 +154,10 @@
     //  - Queue of events, which will be dispatched to local listeners
     //    on next notification.
 
+    private List<MastershipEvent> apiAddedMastershipEvents =
+        new LinkedList<>();
+    private List<MastershipEvent> apiRemovedMastershipEvents =
+        new LinkedList<>();
     private List<SwitchEvent> apiAddedSwitchEvents = new LinkedList<>();
     private List<SwitchEvent> apiRemovedSwitchEvents = new LinkedList<>();
     private List<PortEvent> apiAddedPortEvents = new LinkedList<>();
@@ -255,6 +260,10 @@
          */
         private void processEvents(Collection<EventEntry<TopologyEvent>> events) {
             // Local state for computing the final set of events
+            Map<ByteBuffer, MastershipEvent> addedMastershipEvents =
+                new HashMap<>();
+            Map<ByteBuffer, MastershipEvent> removedMastershipEvents =
+                new HashMap<>();
             Map<ByteBuffer, SwitchEvent> addedSwitchEvents = new HashMap<>();
             Map<ByteBuffer, SwitchEvent> removedSwitchEvents = new HashMap<>();
             Map<ByteBuffer, PortEvent> addedPortEvents = new HashMap<>();
@@ -263,21 +272,22 @@
             Map<ByteBuffer, LinkEvent> removedLinkEvents = new HashMap<>();
             Map<ByteBuffer, HostEvent> addedHostEvents = new HashMap<>();
             Map<ByteBuffer, HostEvent> removedHostEvents = new HashMap<>();
-            Map<ByteBuffer, MastershipEvent> addedMastershipEvents =
-                new HashMap<>();
-            Map<ByteBuffer, MastershipEvent> removedMastershipEvents =
-                new HashMap<>();
+
+            //
+            // Filter the events
+            //
+            events = eventFilter.filterEvents(events);
 
             //
             // Classify and suppress matching events
             //
             for (EventEntry<TopologyEvent> event : events) {
                 TopologyEvent topologyEvent = event.eventData();
+                MastershipEvent mastershipEvent = topologyEvent.getMastershipEvent();
                 SwitchEvent switchEvent = topologyEvent.getSwitchEvent();
                 PortEvent portEvent = topologyEvent.getPortEvent();
                 LinkEvent linkEvent = topologyEvent.getLinkEvent();
                 HostEvent hostEvent = topologyEvent.getHostEvent();
-                MastershipEvent mastershipEvent = topologyEvent.getMastershipEvent();
 
                 //
                 // Extract the events
@@ -287,6 +297,11 @@
                 switch (event.eventType()) {
                     case ENTRY_ADD:
                         log.debug("Topology event ENTRY_ADD: {}", topologyEvent);
+                        if (mastershipEvent != null) {
+                            ByteBuffer id = mastershipEvent.getIDasByteBuffer();
+                            addedMastershipEvents.put(id, mastershipEvent);
+                            removedMastershipEvents.remove(id);
+                        }
                         if (switchEvent != null) {
                             ByteBuffer id = switchEvent.getIDasByteBuffer();
                             addedSwitchEvents.put(id, switchEvent);
@@ -311,14 +326,14 @@
                             removedHostEvents.remove(id);
                             reorderedAddedHostEvents.remove(id);
                         }
-                        if (mastershipEvent != null) {
-                            ByteBuffer id = mastershipEvent.getIDasByteBuffer();
-                            addedMastershipEvents.put(id, mastershipEvent);
-                            removedMastershipEvents.remove(id);
-                        }
                         break;
                     case ENTRY_REMOVE:
                         log.debug("Topology event ENTRY_REMOVE: {}", topologyEvent);
+                        if (mastershipEvent != null) {
+                            ByteBuffer id = mastershipEvent.getIDasByteBuffer();
+                            addedMastershipEvents.remove(id);
+                            removedMastershipEvents.put(id, mastershipEvent);
+                        }
                         if (switchEvent != null) {
                             ByteBuffer id = switchEvent.getIDasByteBuffer();
                             addedSwitchEvents.remove(id);
@@ -343,11 +358,6 @@
                             removedHostEvents.put(id, hostEvent);
                             reorderedAddedHostEvents.remove(id);
                         }
-                        if (mastershipEvent != null) {
-                            ByteBuffer id = mastershipEvent.getIDasByteBuffer();
-                            addedMastershipEvents.remove(id);
-                            removedMastershipEvents.put(id, mastershipEvent);
-                        }
                         break;
                     default:
                         log.error("Unknown topology event {}",
@@ -481,7 +491,9 @@
      * Dispatch Topology Events to the listeners.
      */
     private void dispatchTopologyEvents() {
-        if (apiAddedSwitchEvents.isEmpty() &&
+        if (apiAddedMastershipEvents.isEmpty() &&
+                apiRemovedMastershipEvents.isEmpty() &&
+                apiAddedSwitchEvents.isEmpty() &&
                 apiRemovedSwitchEvents.isEmpty() &&
                 apiAddedPortEvents.isEmpty() &&
                 apiRemovedPortEvents.isEmpty() &&
@@ -497,6 +509,14 @@
             // Debug statements
             // TODO: Those statements should be removed in the future
             //
+            for (MastershipEvent mastershipEvent : apiAddedMastershipEvents) {
+                log.debug("Dispatch Topology Event: ADDED {}",
+                          mastershipEvent);
+            }
+            for (MastershipEvent mastershipEvent : apiRemovedMastershipEvents) {
+                log.debug("Dispatch Topology Event: REMOVED {}",
+                          mastershipEvent);
+            }
             for (SwitchEvent switchEvent : apiAddedSwitchEvents) {
                 log.debug("Dispatch Topology Event: ADDED {}", switchEvent);
             }
@@ -527,6 +547,7 @@
         // Update the metrics
         //
         long totalEvents =
+            apiAddedMastershipEvents.size() + apiRemovedMastershipEvents.size() +
             apiAddedSwitchEvents.size() + apiRemovedSwitchEvents.size() +
             apiAddedPortEvents.size() + apiRemovedPortEvents.size() +
             apiAddedLinkEvents.size() + apiRemovedLinkEvents.size() +
@@ -539,7 +560,9 @@
         //
         for (ITopologyListener listener : this.topologyListeners) {
             TopologyEvents events =
-                new TopologyEvents(kryo.copy(apiAddedSwitchEvents),
+                new TopologyEvents(kryo.copy(apiAddedMastershipEvents),
+                                   kryo.copy(apiRemovedMastershipEvents),
+                                   kryo.copy(apiAddedSwitchEvents),
                                    kryo.copy(apiRemovedSwitchEvents),
                                    kryo.copy(apiAddedPortEvents),
                                    kryo.copy(apiRemovedPortEvents),
@@ -553,6 +576,8 @@
         //
         // Cleanup
         //
+        apiAddedMastershipEvents.clear();
+        apiRemovedMastershipEvents.clear();
         apiAddedSwitchEvents.clear();
         apiRemovedSwitchEvents.clear();
         apiAddedPortEvents.clear();
@@ -614,6 +639,31 @@
     }
 
     /**
+     * Mastership updated event.
+     *
+     * @param mastershipEvent the mastership event.
+     */
+    @Override
+    public void putSwitchMastershipEvent(MastershipEvent mastershipEvent) {
+        // Send out notification
+        TopologyEvent topologyEvent =
+            new TopologyEvent(mastershipEvent,
+                              registryService.getOnosInstanceId());
+        eventChannel.addEntry(topologyEvent.getID(), topologyEvent);
+    }
+
+    /**
+     * Mastership removed event.
+     *
+     * @param mastershipEvent the mastership event.
+     */
+    @Override
+    public void removeSwitchMastershipEvent(MastershipEvent mastershipEvent) {
+        // Send out notification
+        eventChannel.removeEntry(mastershipEvent.getID());
+    }
+
+    /**
      * Switch discovered event.
      *
      * @param switchEvent the switch event.
@@ -924,28 +974,29 @@
     //
 
     /**
-     * Mastership updated event.
+     * Processes added Switch Mastership event.
      *
-     * @param mastershipEvent the mastership event.
+     * @param mastershipEvent the MastershipEvent to process.
      */
-    @Override
-    public void putSwitchMastershipEvent(MastershipEvent mastershipEvent) {
-        // Send out notification
-        TopologyEvent topologyEvent =
-            new TopologyEvent(mastershipEvent,
-                              registryService.getOnosInstanceId());
-        eventChannel.addEntry(topologyEvent.getID(), topologyEvent);
+    @GuardedBy("topology.writeLock")
+    private void processAddedMastershipEvent(MastershipEvent mastershipEvent) {
+        log.debug("Processing added Mastership event {}",
+                  mastershipEvent);
+        // TODO: Not implemented/used yet.
+        apiAddedMastershipEvents.add(mastershipEvent);
     }
 
     /**
-     * Mastership removed event.
+     * Processes removed Switch Mastership event.
      *
-     * @param mastershipEvent the mastership event.
+     * @param mastershipEvent the MastershipEvent to process.
      */
-    @Override
-    public void removeSwitchMastershipEvent(MastershipEvent mastershipEvent) {
-        // Send out notification
-        eventChannel.removeEntry(mastershipEvent.getID());
+    @GuardedBy("topology.writeLock")
+    private void processRemovedMastershipEvent(MastershipEvent mastershipEvent) {
+        log.debug("Processing removed Mastership event {}",
+                  mastershipEvent);
+        // TODO: Not implemented/used yet.
+        apiRemovedMastershipEvents.add(mastershipEvent);
     }
 
     /**
@@ -1333,30 +1384,6 @@
     }
 
     /**
-     * Processes added Switch Mastership event.
-     *
-     * @param mastershipEvent the MastershipEvent to process.
-     */
-    @GuardedBy("topology.writeLock")
-    private void processAddedMastershipEvent(MastershipEvent mastershipEvent) {
-        log.debug("Processing added Mastership event {}",
-                  mastershipEvent);
-        // TODO: Not implemented/used yet.
-    }
-
-    /**
-     * Processes removed Switch Mastership event.
-     *
-     * @param mastershipEvent the MastershipEvent to process.
-     */
-    @GuardedBy("topology.writeLock")
-    private void processRemovedMastershipEvent(MastershipEvent mastershipEvent) {
-        log.debug("Processing removed Mastership event {}",
-                  mastershipEvent);
-        // TODO: Not implemented/used yet.
-    }
-
-    /**
      * Read the whole topology from the database.
      *
      * @return a collection of EventEntry-encapsulated Topology Events for
diff --git a/src/main/java/net/onrc/onos/core/topology/web/serializers/TopologyEventsSerializer.java b/src/main/java/net/onrc/onos/core/topology/web/serializers/TopologyEventsSerializer.java
index 1d0a38b..b117404 100644
--- a/src/main/java/net/onrc/onos/core/topology/web/serializers/TopologyEventsSerializer.java
+++ b/src/main/java/net/onrc/onos/core/topology/web/serializers/TopologyEventsSerializer.java
@@ -4,6 +4,7 @@
 
 import net.onrc.onos.core.topology.HostEvent;
 import net.onrc.onos.core.topology.LinkEvent;
+import net.onrc.onos.core.topology.MastershipEvent;
 import net.onrc.onos.core.topology.PortEvent;
 import net.onrc.onos.core.topology.SwitchEvent;
 import net.onrc.onos.core.topology.TopologyEvents;
@@ -40,6 +41,20 @@
         // Start the object
         jsonGenerator.writeStartObject();
 
+        // Output the added switch mastership array
+        jsonGenerator.writeArrayFieldStart("addedSwitchMasterships");
+        for (final MastershipEvent mastershipEvent : topologyEvents.getAddedMastershipEvents()) {
+            jsonGenerator.writeObject(mastershipEvent);
+        }
+        jsonGenerator.writeEndArray();
+
+        // Output the removed switch mastership array
+        jsonGenerator.writeArrayFieldStart("removedSwitchMasterships");
+        for (final MastershipEvent mastershipEvent : topologyEvents.getRemovedMastershipEvents()) {
+            jsonGenerator.writeObject(mastershipEvent);
+        }
+        jsonGenerator.writeEndArray();
+
         // Output the added switches array
         jsonGenerator.writeArrayFieldStart("addedSwitches");
         for (final SwitchEvent switchEvent : topologyEvents.getAddedSwitchEvents()) {