Committed by
Gerrit Code Review
Implement map listener in DistributedMcastStore
Fix the problem that only local delegation is triggered Change-Id: Ibe7b4a6abb447b9a8e3a0959882ef2da0d21f4be
Showing
1 changed file
with
84 additions
and
45 deletions
| ... | @@ -31,14 +31,18 @@ import org.onosproject.net.mcast.McastStoreDelegate; | ... | @@ -31,14 +31,18 @@ import org.onosproject.net.mcast.McastStoreDelegate; |
| 31 | import org.onosproject.store.AbstractStore; | 31 | import org.onosproject.store.AbstractStore; |
| 32 | import org.onosproject.store.serializers.KryoNamespaces; | 32 | import org.onosproject.store.serializers.KryoNamespaces; |
| 33 | import org.onosproject.store.service.ConsistentMap; | 33 | import org.onosproject.store.service.ConsistentMap; |
| 34 | +import org.onosproject.store.service.MapEvent; | ||
| 35 | +import org.onosproject.store.service.MapEventListener; | ||
| 34 | import org.onosproject.store.service.Serializer; | 36 | import org.onosproject.store.service.Serializer; |
| 35 | import org.onosproject.store.service.StorageService; | 37 | import org.onosproject.store.service.StorageService; |
| 36 | import org.slf4j.Logger; | 38 | import org.slf4j.Logger; |
| 37 | 39 | ||
| 38 | import java.util.Map; | 40 | import java.util.Map; |
| 39 | import java.util.Set; | 41 | import java.util.Set; |
| 42 | +import java.util.concurrent.ConcurrentHashMap; | ||
| 40 | import java.util.concurrent.atomic.AtomicReference; | 43 | import java.util.concurrent.atomic.AtomicReference; |
| 41 | 44 | ||
| 45 | +import static com.google.common.base.Preconditions.checkState; | ||
| 42 | import static org.slf4j.LoggerFactory.getLogger; | 46 | import static org.slf4j.LoggerFactory.getLogger; |
| 43 | 47 | ||
| 44 | /** | 48 | /** |
| ... | @@ -62,11 +66,16 @@ public class DistributedMcastStore extends AbstractStore<McastEvent, McastStoreD | ... | @@ -62,11 +66,16 @@ public class DistributedMcastStore extends AbstractStore<McastEvent, McastStoreD |
| 62 | 66 | ||
| 63 | protected ConsistentMap<McastRoute, MulticastData> mcastRib; | 67 | protected ConsistentMap<McastRoute, MulticastData> mcastRib; |
| 64 | protected Map<McastRoute, MulticastData> mcastRoutes; | 68 | protected Map<McastRoute, MulticastData> mcastRoutes; |
| 69 | + private final MapEventListener<McastRoute, MulticastData> mcastMapListener = | ||
| 70 | + new McastMapListener(); | ||
| 65 | 71 | ||
| 72 | + // NOTE: MapEvent cannot provide correct old value of sink since MulticastData | ||
| 73 | + // is a object reference. Use this localSink to track sink. | ||
| 74 | + private Map<McastRoute, Set<ConnectPoint>> localSink = | ||
| 75 | + new ConcurrentHashMap<>(); | ||
| 66 | 76 | ||
| 67 | @Activate | 77 | @Activate |
| 68 | public void activate() { | 78 | public void activate() { |
| 69 | - | ||
| 70 | mcastRib = storageService.<McastRoute, MulticastData>consistentMapBuilder() | 79 | mcastRib = storageService.<McastRoute, MulticastData>consistentMapBuilder() |
| 71 | .withName(MCASTRIB) | 80 | .withName(MCASTRIB) |
| 72 | .withSerializer(Serializer.using(KryoNamespace.newBuilder() | 81 | .withSerializer(Serializer.using(KryoNamespace.newBuilder() |
| ... | @@ -79,10 +88,9 @@ public class DistributedMcastStore extends AbstractStore<McastEvent, McastStoreD | ... | @@ -79,10 +88,9 @@ public class DistributedMcastStore extends AbstractStore<McastEvent, McastStoreD |
| 79 | ).build())) | 88 | ).build())) |
| 80 | //.withRelaxedReadConsistency() | 89 | //.withRelaxedReadConsistency() |
| 81 | .build(); | 90 | .build(); |
| 82 | - | 91 | + mcastRib.addListener(mcastMapListener); |
| 83 | mcastRoutes = mcastRib.asJavaMap(); | 92 | mcastRoutes = mcastRib.asJavaMap(); |
| 84 | 93 | ||
| 85 | - | ||
| 86 | log.info("Started"); | 94 | log.info("Started"); |
| 87 | } | 95 | } |
| 88 | 96 | ||
| ... | @@ -95,16 +103,10 @@ public class DistributedMcastStore extends AbstractStore<McastEvent, McastStoreD | ... | @@ -95,16 +103,10 @@ public class DistributedMcastStore extends AbstractStore<McastEvent, McastStoreD |
| 95 | public void storeRoute(McastRoute route, Type operation) { | 103 | public void storeRoute(McastRoute route, Type operation) { |
| 96 | switch (operation) { | 104 | switch (operation) { |
| 97 | case ADD: | 105 | case ADD: |
| 98 | - if (mcastRoutes.putIfAbsent(route, MulticastData.empty()) == null) { | 106 | + mcastRoutes.putIfAbsent(route, MulticastData.empty()); |
| 99 | - delegate.notify(new McastEvent(McastEvent.Type.ROUTE_ADDED, | ||
| 100 | - McastRouteInfo.mcastRouteInfo(route))); | ||
| 101 | - } | ||
| 102 | break; | 107 | break; |
| 103 | case REMOVE: | 108 | case REMOVE: |
| 104 | - if (mcastRoutes.remove(route) != null) { | 109 | + mcastRoutes.remove(route); |
| 105 | - delegate.notify(new McastEvent(McastEvent.Type.ROUTE_REMOVED, | ||
| 106 | - McastRouteInfo.mcastRouteInfo(route))); | ||
| 107 | - } | ||
| 108 | break; | 110 | break; |
| 109 | default: | 111 | default: |
| 110 | log.warn("Unknown mcast operation type: {}", operation); | 112 | log.warn("Unknown mcast operation type: {}", operation); |
| ... | @@ -121,15 +123,6 @@ public class DistributedMcastStore extends AbstractStore<McastEvent, McastStoreD | ... | @@ -121,15 +123,6 @@ public class DistributedMcastStore extends AbstractStore<McastEvent, McastStoreD |
| 121 | } | 123 | } |
| 122 | return v; | 124 | return v; |
| 123 | }); | 125 | }); |
| 124 | - | ||
| 125 | - | ||
| 126 | - if (data != null) { | ||
| 127 | - delegate.notify(new McastEvent(McastEvent.Type.SOURCE_ADDED, | ||
| 128 | - McastRouteInfo.mcastRouteInfo(route, | ||
| 129 | - data.sinks(), | ||
| 130 | - source))); | ||
| 131 | - } | ||
| 132 | - | ||
| 133 | } | 126 | } |
| 134 | 127 | ||
| 135 | @Override | 128 | @Override |
| ... | @@ -152,31 +145,6 @@ public class DistributedMcastStore extends AbstractStore<McastEvent, McastStoreD | ... | @@ -152,31 +145,6 @@ public class DistributedMcastStore extends AbstractStore<McastEvent, McastStoreD |
| 152 | } | 145 | } |
| 153 | return v; | 146 | return v; |
| 154 | }); | 147 | }); |
| 155 | - | ||
| 156 | - | ||
| 157 | - if (data != null) { | ||
| 158 | - switch (operation) { | ||
| 159 | - case ADD: | ||
| 160 | - delegate.notify(new McastEvent( | ||
| 161 | - McastEvent.Type.SINK_ADDED, | ||
| 162 | - McastRouteInfo.mcastRouteInfo(route, | ||
| 163 | - sink, | ||
| 164 | - data.source()))); | ||
| 165 | - break; | ||
| 166 | - case REMOVE: | ||
| 167 | - if (data != null) { | ||
| 168 | - delegate.notify(new McastEvent( | ||
| 169 | - McastEvent.Type.SINK_REMOVED, | ||
| 170 | - McastRouteInfo.mcastRouteInfo(route, | ||
| 171 | - sink, | ||
| 172 | - data.source()))); | ||
| 173 | - } | ||
| 174 | - break; | ||
| 175 | - default: | ||
| 176 | - log.warn("Unknown mcast operation type: {}", operation); | ||
| 177 | - } | ||
| 178 | - } | ||
| 179 | - | ||
| 180 | } | 148 | } |
| 181 | 149 | ||
| 182 | @Override | 150 | @Override |
| ... | @@ -194,4 +162,75 @@ public class DistributedMcastStore extends AbstractStore<McastEvent, McastStoreD | ... | @@ -194,4 +162,75 @@ public class DistributedMcastStore extends AbstractStore<McastEvent, McastStoreD |
| 194 | return mcastRoutes.keySet(); | 162 | return mcastRoutes.keySet(); |
| 195 | } | 163 | } |
| 196 | 164 | ||
| 165 | + private class McastMapListener implements MapEventListener<McastRoute, MulticastData> { | ||
| 166 | + @Override | ||
| 167 | + public void event(MapEvent<McastRoute, MulticastData> event) { | ||
| 168 | + McastRoute route = event.key(); | ||
| 169 | + MulticastData newValue, oldValue; | ||
| 170 | + | ||
| 171 | + switch (event.type()) { | ||
| 172 | + case INSERT: | ||
| 173 | + checkState(event.newValue() != null, "Map insert event should have newValue"); | ||
| 174 | + newValue = event.newValue().value(); | ||
| 175 | + if (newValue.source() != null) { | ||
| 176 | + notifyDelegate(new McastEvent(McastEvent.Type.SOURCE_ADDED, | ||
| 177 | + McastRouteInfo.mcastRouteInfo(route, | ||
| 178 | + newValue.sinks(), newValue.source()))); | ||
| 179 | + } | ||
| 180 | + if (!newValue.sinks().isEmpty()) { | ||
| 181 | + newValue.sinks().forEach(sink -> { | ||
| 182 | + notifyDelegate(new McastEvent(McastEvent.Type.SINK_ADDED, | ||
| 183 | + McastRouteInfo.mcastRouteInfo(route, | ||
| 184 | + sink, newValue.source()))); | ||
| 185 | + }); | ||
| 186 | + } | ||
| 187 | + if (newValue.source() == null && newValue.sinks().isEmpty()) { | ||
| 188 | + notifyDelegate(new McastEvent(McastEvent.Type.ROUTE_ADDED, | ||
| 189 | + McastRouteInfo.mcastRouteInfo(route))); | ||
| 190 | + } | ||
| 191 | + localSink.put(route, newValue.sinks()); | ||
| 192 | + break; | ||
| 193 | + case REMOVE: | ||
| 194 | + checkState(event.oldValue() != null, "Map remove event should have oldValue"); | ||
| 195 | + oldValue = event.oldValue().value(); | ||
| 196 | + notifyDelegate(new McastEvent(McastEvent.Type.ROUTE_REMOVED, | ||
| 197 | + McastRouteInfo.mcastRouteInfo(route))); | ||
| 198 | + oldValue.sinks().forEach(sink -> { | ||
| 199 | + notifyDelegate(new McastEvent( | ||
| 200 | + McastEvent.Type.SINK_REMOVED, | ||
| 201 | + McastRouteInfo.mcastRouteInfo(route, sink, oldValue.source()))); | ||
| 202 | + }); | ||
| 203 | + localSink.remove(route); | ||
| 204 | + break; | ||
| 205 | + case UPDATE: | ||
| 206 | + checkState(event.newValue() != null, "Map update event should have newValue"); | ||
| 207 | + checkState(event.oldValue() != null, "Map update event should have oldValue"); | ||
| 208 | + newValue = event.newValue().value(); | ||
| 209 | + oldValue = event.oldValue().value(); | ||
| 210 | + if (newValue.source() != null && oldValue.source() == null) { | ||
| 211 | + notifyDelegate(new McastEvent(McastEvent.Type.SOURCE_ADDED, | ||
| 212 | + McastRouteInfo.mcastRouteInfo(route, | ||
| 213 | + newValue.sinks(), newValue.source()))); | ||
| 214 | + } | ||
| 215 | + newValue.sinks().stream() | ||
| 216 | + .filter(sink -> !localSink.get(route).contains(sink)) | ||
| 217 | + .forEach(addedSink -> { | ||
| 218 | + notifyDelegate(new McastEvent(McastEvent.Type.SINK_ADDED, | ||
| 219 | + McastRouteInfo.mcastRouteInfo(route, | ||
| 220 | + addedSink, newValue.source()))); | ||
| 221 | + }); | ||
| 222 | + localSink.get(route).stream() | ||
| 223 | + .filter(sink -> !newValue.sinks().contains(sink)) | ||
| 224 | + .forEach(removedSink -> { | ||
| 225 | + notifyDelegate(new McastEvent(McastEvent.Type.SINK_REMOVED, | ||
| 226 | + McastRouteInfo.mcastRouteInfo(route, | ||
| 227 | + removedSink, newValue.source()))); | ||
| 228 | + }); | ||
| 229 | + localSink.put(route, newValue.sinks()); | ||
| 230 | + break; | ||
| 231 | + default: | ||
| 232 | + break; | ||
| 233 | + } | ||
| 234 | + } | ||
| 235 | + } | ||
| 197 | } | 236 | } | ... | ... |
-
Please register or login to post a comment