add check for duplicate MastershipEvents to DeviceManager
Change-Id: I2753366b29ef32fa77ebcefff4b2202f1afe0006
Showing
1 changed file
with
34 additions
and
0 deletions
| ... | @@ -29,6 +29,7 @@ import org.apache.felix.scr.annotations.ReferenceCardinality; | ... | @@ -29,6 +29,7 @@ import org.apache.felix.scr.annotations.ReferenceCardinality; |
| 29 | import org.apache.felix.scr.annotations.Service; | 29 | import org.apache.felix.scr.annotations.Service; |
| 30 | import org.onlab.onos.cluster.ClusterService; | 30 | import org.onlab.onos.cluster.ClusterService; |
| 31 | import org.onlab.onos.cluster.NodeId; | 31 | import org.onlab.onos.cluster.NodeId; |
| 32 | +import org.onlab.onos.cluster.RoleInfo; | ||
| 32 | import org.onlab.onos.event.AbstractListenerRegistry; | 33 | import org.onlab.onos.event.AbstractListenerRegistry; |
| 33 | import org.onlab.onos.event.EventDeliveryService; | 34 | import org.onlab.onos.event.EventDeliveryService; |
| 34 | import org.onlab.onos.mastership.MastershipEvent; | 35 | import org.onlab.onos.mastership.MastershipEvent; |
| ... | @@ -58,6 +59,8 @@ import org.onlab.onos.net.provider.AbstractProviderRegistry; | ... | @@ -58,6 +59,8 @@ import org.onlab.onos.net.provider.AbstractProviderRegistry; |
| 58 | import org.onlab.onos.net.provider.AbstractProviderService; | 59 | import org.onlab.onos.net.provider.AbstractProviderService; |
| 59 | import org.slf4j.Logger; | 60 | import org.slf4j.Logger; |
| 60 | 61 | ||
| 62 | +import com.google.common.collect.HashMultimap; | ||
| 63 | + | ||
| 61 | /** | 64 | /** |
| 62 | * Provides implementation of the device SB & NB APIs. | 65 | * Provides implementation of the device SB & NB APIs. |
| 63 | */ | 66 | */ |
| ... | @@ -387,6 +390,12 @@ public class DeviceManager | ... | @@ -387,6 +390,12 @@ public class DeviceManager |
| 387 | // Intercepts mastership events | 390 | // Intercepts mastership events |
| 388 | private class InternalMastershipListener implements MastershipListener { | 391 | private class InternalMastershipListener implements MastershipListener { |
| 389 | 392 | ||
| 393 | + // random cache size | ||
| 394 | + private final int cacheSize = 5; | ||
| 395 | + // temporarily stores term number + events to check for duplicates. A hack. | ||
| 396 | + private HashMultimap<Integer, RoleInfo> eventCache = | ||
| 397 | + HashMultimap.create(); | ||
| 398 | + | ||
| 390 | @Override | 399 | @Override |
| 391 | public void event(MastershipEvent event) { | 400 | public void event(MastershipEvent event) { |
| 392 | final DeviceId did = event.subject(); | 401 | final DeviceId did = event.subject(); |
| ... | @@ -395,6 +404,13 @@ public class DeviceManager | ... | @@ -395,6 +404,13 @@ public class DeviceManager |
| 395 | if (myNodeId.equals(event.roleInfo().master())) { | 404 | if (myNodeId.equals(event.roleInfo().master())) { |
| 396 | MastershipTerm term = termService.getMastershipTerm(did); | 405 | MastershipTerm term = termService.getMastershipTerm(did); |
| 397 | 406 | ||
| 407 | + // TODO duplicate suppression should probably occur in the MastershipManager | ||
| 408 | + // itself, so listeners that can't deal with duplicates don't have to | ||
| 409 | + // so this check themselves. | ||
| 410 | + if (checkDuplicate(event.roleInfo(), term.termNumber())) { | ||
| 411 | + return; | ||
| 412 | + } | ||
| 413 | + | ||
| 398 | if (!myNodeId.equals(term.master())) { | 414 | if (!myNodeId.equals(term.master())) { |
| 399 | // something went wrong in consistency, let go | 415 | // something went wrong in consistency, let go |
| 400 | log.warn("Mastership has changed after this event." | 416 | log.warn("Mastership has changed after this event." |
| ... | @@ -436,6 +452,24 @@ public class DeviceManager | ... | @@ -436,6 +452,24 @@ public class DeviceManager |
| 436 | applyRole(did, MastershipRole.STANDBY); | 452 | applyRole(did, MastershipRole.STANDBY); |
| 437 | } | 453 | } |
| 438 | } | 454 | } |
| 455 | + | ||
| 456 | + // checks for duplicate event, returning true if one is found. | ||
| 457 | + private boolean checkDuplicate(RoleInfo roleInfo, int term) { | ||
| 458 | + synchronized (eventCache) { | ||
| 459 | + if (eventCache.get(term).contains(roleInfo)) { | ||
| 460 | + log.info("duplicate event detected; ignoring"); | ||
| 461 | + return true; | ||
| 462 | + } else { | ||
| 463 | + eventCache.put(term, roleInfo); | ||
| 464 | + // purge by-term oldest entries to keep the cache size under limit | ||
| 465 | + if (eventCache.size() > cacheSize) { | ||
| 466 | + eventCache.removeAll(term - cacheSize); | ||
| 467 | + } | ||
| 468 | + return false; | ||
| 469 | + } | ||
| 470 | + } | ||
| 471 | + } | ||
| 472 | + | ||
| 439 | } | 473 | } |
| 440 | 474 | ||
| 441 | // Store delegate to re-post events emitted from the store. | 475 | // Store delegate to re-post events emitted from the store. | ... | ... |
-
Please register or login to post a comment