Committed by
Ray Milkey
ONOS-1433: Avoid two EC maps for same data with different keys
Change-Id: I2377507e52fa1942cbea247c2f9d08d8f0587f22
Showing
1 changed file
with
43 additions
and
51 deletions
... | @@ -117,8 +117,8 @@ public class DistributedGroupStore | ... | @@ -117,8 +117,8 @@ public class DistributedGroupStore |
117 | private EventuallyConsistentMap<GroupStoreKeyMapKey, | 117 | private EventuallyConsistentMap<GroupStoreKeyMapKey, |
118 | StoredGroupEntry> groupStoreEntriesByKey = null; | 118 | StoredGroupEntry> groupStoreEntriesByKey = null; |
119 | // Per device group table with (device id + group id) as key | 119 | // Per device group table with (device id + group id) as key |
120 | - private EventuallyConsistentMap<GroupStoreIdMapKey, | 120 | + private final ConcurrentMap<DeviceId, ConcurrentMap<GroupId, StoredGroupEntry>> |
121 | - StoredGroupEntry> groupStoreEntriesById = null; | 121 | + groupEntriesById = new ConcurrentHashMap<>(); |
122 | private EventuallyConsistentMap<GroupStoreKeyMapKey, | 122 | private EventuallyConsistentMap<GroupStoreKeyMapKey, |
123 | StoredGroupEntry> auditPendingReqQueue = null; | 123 | StoredGroupEntry> auditPendingReqQueue = null; |
124 | private final ConcurrentMap<DeviceId, ConcurrentMap<GroupId, Group>> | 124 | private final ConcurrentMap<DeviceId, ConcurrentMap<GroupId, Group>> |
... | @@ -203,21 +203,9 @@ public class DistributedGroupStore | ... | @@ -203,21 +203,9 @@ public class DistributedGroupStore |
203 | .withSerializer(kryoBuilder) | 203 | .withSerializer(kryoBuilder) |
204 | .withClockService(new GroupStoreLogicalClockManager<>()) | 204 | .withClockService(new GroupStoreLogicalClockManager<>()) |
205 | .build(); | 205 | .build(); |
206 | + groupStoreEntriesByKey.addListener(new GroupStoreKeyMapListener()); | ||
206 | log.trace("Current size {}", groupStoreEntriesByKey.size()); | 207 | log.trace("Current size {}", groupStoreEntriesByKey.size()); |
207 | 208 | ||
208 | - log.debug("Creating EC map groupstoreidmap"); | ||
209 | - EventuallyConsistentMapBuilder<GroupStoreIdMapKey, StoredGroupEntry> | ||
210 | - idMapBuilder = storageService.eventuallyConsistentMapBuilder(); | ||
211 | - | ||
212 | - groupStoreEntriesById = idMapBuilder | ||
213 | - .withName("groupstoreidmap") | ||
214 | - .withSerializer(kryoBuilder) | ||
215 | - .withClockService(new GroupStoreLogicalClockManager<>()) | ||
216 | - .build(); | ||
217 | - | ||
218 | - groupStoreEntriesById.addListener(new GroupStoreIdMapListener()); | ||
219 | - log.trace("Current size {}", groupStoreEntriesById.size()); | ||
220 | - | ||
221 | log.debug("Creating EC map pendinggroupkeymap"); | 209 | log.debug("Creating EC map pendinggroupkeymap"); |
222 | EventuallyConsistentMapBuilder<GroupStoreKeyMapKey, StoredGroupEntry> | 210 | EventuallyConsistentMapBuilder<GroupStoreKeyMapKey, StoredGroupEntry> |
223 | auditMapBuilder = storageService.eventuallyConsistentMapBuilder(); | 211 | auditMapBuilder = storageService.eventuallyConsistentMapBuilder(); |
... | @@ -235,7 +223,6 @@ public class DistributedGroupStore | ... | @@ -235,7 +223,6 @@ public class DistributedGroupStore |
235 | @Deactivate | 223 | @Deactivate |
236 | public void deactivate() { | 224 | public void deactivate() { |
237 | groupStoreEntriesByKey.destroy(); | 225 | groupStoreEntriesByKey.destroy(); |
238 | - groupStoreEntriesById.destroy(); | ||
239 | auditPendingReqQueue.destroy(); | 226 | auditPendingReqQueue.destroy(); |
240 | log.info("Stopped"); | 227 | log.info("Stopped"); |
241 | } | 228 | } |
... | @@ -245,6 +232,11 @@ public class DistributedGroupStore | ... | @@ -245,6 +232,11 @@ public class DistributedGroupStore |
245 | return NewConcurrentHashMap.<GroupId, Group>ifNeeded(); | 232 | return NewConcurrentHashMap.<GroupId, Group>ifNeeded(); |
246 | } | 233 | } |
247 | 234 | ||
235 | + private static NewConcurrentHashMap<GroupId, StoredGroupEntry> | ||
236 | + lazyEmptyGroupIdTable() { | ||
237 | + return NewConcurrentHashMap.<GroupId, StoredGroupEntry>ifNeeded(); | ||
238 | + } | ||
239 | + | ||
248 | /** | 240 | /** |
249 | * Returns the group store eventual consistent key map. | 241 | * Returns the group store eventual consistent key map. |
250 | * | 242 | * |
... | @@ -256,13 +248,14 @@ public class DistributedGroupStore | ... | @@ -256,13 +248,14 @@ public class DistributedGroupStore |
256 | } | 248 | } |
257 | 249 | ||
258 | /** | 250 | /** |
259 | - * Returns the group store eventual consistent id map. | 251 | + * Returns the group id table for specified device. |
260 | * | 252 | * |
261 | - * @return Map representing group id table. | 253 | + * @param deviceId identifier of the device |
254 | + * @return Map representing group key table of given device. | ||
262 | */ | 255 | */ |
263 | - private EventuallyConsistentMap<GroupStoreIdMapKey, StoredGroupEntry> | 256 | + private ConcurrentMap<GroupId, StoredGroupEntry> getGroupIdTable(DeviceId deviceId) { |
264 | - getGroupStoreIdMap() { | 257 | + return createIfAbsentUnchecked(groupEntriesById, |
265 | - return groupStoreEntriesById; | 258 | + deviceId, lazyEmptyGroupIdTable()); |
266 | } | 259 | } |
267 | 260 | ||
268 | /** | 261 | /** |
... | @@ -342,8 +335,7 @@ public class DistributedGroupStore | ... | @@ -342,8 +335,7 @@ public class DistributedGroupStore |
342 | 335 | ||
343 | private StoredGroupEntry getStoredGroupEntry(DeviceId deviceId, | 336 | private StoredGroupEntry getStoredGroupEntry(DeviceId deviceId, |
344 | GroupId groupId) { | 337 | GroupId groupId) { |
345 | - return getGroupStoreIdMap().get(new GroupStoreIdMapKey(deviceId, | 338 | + return getGroupIdTable(deviceId).get(groupId); |
346 | - groupId)); | ||
347 | } | 339 | } |
348 | 340 | ||
349 | private int getFreeGroupIdValue(DeviceId deviceId) { | 341 | private int getFreeGroupIdValue(DeviceId deviceId) { |
... | @@ -447,9 +439,10 @@ public class DistributedGroupStore | ... | @@ -447,9 +439,10 @@ public class DistributedGroupStore |
447 | getGroupStoreKeyMap(). | 439 | getGroupStoreKeyMap(). |
448 | put(new GroupStoreKeyMapKey(groupDesc.deviceId(), | 440 | put(new GroupStoreKeyMapKey(groupDesc.deviceId(), |
449 | groupDesc.appCookie()), group); | 441 | groupDesc.appCookie()), group); |
450 | - getGroupStoreIdMap(). | 442 | + // Ensure it also inserted into group id based table to |
451 | - put(new GroupStoreIdMapKey(groupDesc.deviceId(), | 443 | + // avoid any chances of duplication in group id generation |
452 | - id), group); | 444 | + getGroupIdTable(groupDesc.deviceId()). |
445 | + put(id, group); | ||
453 | notifyDelegate(new GroupEvent(GroupEvent.Type.GROUP_ADD_REQUESTED, | 446 | notifyDelegate(new GroupEvent(GroupEvent.Type.GROUP_ADD_REQUESTED, |
454 | group)); | 447 | group)); |
455 | } | 448 | } |
... | @@ -531,18 +524,12 @@ public class DistributedGroupStore | ... | @@ -531,18 +524,12 @@ public class DistributedGroupStore |
531 | newGroup.setLife(oldGroup.life()); | 524 | newGroup.setLife(oldGroup.life()); |
532 | newGroup.setPackets(oldGroup.packets()); | 525 | newGroup.setPackets(oldGroup.packets()); |
533 | newGroup.setBytes(oldGroup.bytes()); | 526 | newGroup.setBytes(oldGroup.bytes()); |
534 | - // Remove the old entry from maps and add new entry using new key | 527 | + //Update the group entry in groupkey based map. |
535 | - getGroupStoreKeyMap().remove(new GroupStoreKeyMapKey(oldGroup.deviceId(), | 528 | + //Update to groupid based map will happen in the |
536 | - oldGroup.appCookie())); | 529 | + //groupkey based map update listener |
537 | - getGroupStoreIdMap().remove(new GroupStoreIdMapKey(oldGroup.deviceId(), | ||
538 | - oldGroup.id())); | ||
539 | getGroupStoreKeyMap(). | 530 | getGroupStoreKeyMap(). |
540 | put(new GroupStoreKeyMapKey(newGroup.deviceId(), | 531 | put(new GroupStoreKeyMapKey(newGroup.deviceId(), |
541 | newGroup.appCookie()), newGroup); | 532 | newGroup.appCookie()), newGroup); |
542 | - getGroupStoreIdMap(). | ||
543 | - put(new GroupStoreIdMapKey(newGroup.deviceId(), | ||
544 | - newGroup.id()), newGroup); | ||
545 | - | ||
546 | notifyDelegate(new GroupEvent(Type.GROUP_UPDATE_REQUESTED, newGroup)); | 533 | notifyDelegate(new GroupEvent(Type.GROUP_UPDATE_REQUESTED, newGroup)); |
547 | } | 534 | } |
548 | } | 535 | } |
... | @@ -663,10 +650,10 @@ public class DistributedGroupStore | ... | @@ -663,10 +650,10 @@ public class DistributedGroupStore |
663 | getGroupStoreKeyMap(). | 650 | getGroupStoreKeyMap(). |
664 | put(new GroupStoreKeyMapKey(existing.deviceId(), | 651 | put(new GroupStoreKeyMapKey(existing.deviceId(), |
665 | existing.appCookie()), existing); | 652 | existing.appCookie()), existing); |
666 | - getGroupStoreIdMap(). | ||
667 | - put(new GroupStoreIdMapKey(existing.deviceId(), | ||
668 | - existing.id()), existing); | ||
669 | } | 653 | } |
654 | + } else { | ||
655 | + log.warn("addOrUpdateGroupEntry: Group update " | ||
656 | + + "happening for a non-existing entry in the map"); | ||
670 | } | 657 | } |
671 | 658 | ||
672 | if (event != null) { | 659 | if (event != null) { |
... | @@ -689,10 +676,10 @@ public class DistributedGroupStore | ... | @@ -689,10 +676,10 @@ public class DistributedGroupStore |
689 | + "entry {} in device {}", | 676 | + "entry {} in device {}", |
690 | group.id(), | 677 | group.id(), |
691 | group.deviceId()); | 678 | group.deviceId()); |
679 | + //Removal from groupid based map will happen in the | ||
680 | + //map update listener | ||
692 | getGroupStoreKeyMap().remove(new GroupStoreKeyMapKey(existing.deviceId(), | 681 | getGroupStoreKeyMap().remove(new GroupStoreKeyMapKey(existing.deviceId(), |
693 | existing.appCookie())); | 682 | existing.appCookie())); |
694 | - getGroupStoreIdMap().remove(new GroupStoreIdMapKey(existing.deviceId(), | ||
695 | - existing.id())); | ||
696 | notifyDelegate(new GroupEvent(Type.GROUP_REMOVED, existing)); | 683 | notifyDelegate(new GroupEvent(Type.GROUP_REMOVED, existing)); |
697 | } | 684 | } |
698 | } | 685 | } |
... | @@ -770,10 +757,10 @@ public class DistributedGroupStore | ... | @@ -770,10 +757,10 @@ public class DistributedGroupStore |
770 | log.warn("Unknown group operation type {}", operation.opType()); | 757 | log.warn("Unknown group operation type {}", operation.opType()); |
771 | } | 758 | } |
772 | 759 | ||
760 | + //Removal from groupid based map will happen in the | ||
761 | + //map update listener | ||
773 | getGroupStoreKeyMap().remove(new GroupStoreKeyMapKey(existing.deviceId(), | 762 | getGroupStoreKeyMap().remove(new GroupStoreKeyMapKey(existing.deviceId(), |
774 | existing.appCookie())); | 763 | existing.appCookie())); |
775 | - getGroupStoreIdMap().remove(new GroupStoreIdMapKey(existing.deviceId(), | ||
776 | - existing.id())); | ||
777 | } | 764 | } |
778 | 765 | ||
779 | @Override | 766 | @Override |
... | @@ -829,35 +816,40 @@ public class DistributedGroupStore | ... | @@ -829,35 +816,40 @@ public class DistributedGroupStore |
829 | } | 816 | } |
830 | 817 | ||
831 | /** | 818 | /** |
832 | - * Map handler to receive any events when the group map is updated. | 819 | + * Map handler to receive any events when the group key map is updated. |
833 | */ | 820 | */ |
834 | - private class GroupStoreIdMapListener implements | 821 | + private class GroupStoreKeyMapListener implements |
835 | - EventuallyConsistentMapListener<GroupStoreIdMapKey, StoredGroupEntry> { | 822 | + EventuallyConsistentMapListener<GroupStoreKeyMapKey, StoredGroupEntry> { |
836 | 823 | ||
837 | @Override | 824 | @Override |
838 | - public void event(EventuallyConsistentMapEvent<GroupStoreIdMapKey, | 825 | + public void event(EventuallyConsistentMapEvent<GroupStoreKeyMapKey, |
839 | StoredGroupEntry> mapEvent) { | 826 | StoredGroupEntry> mapEvent) { |
840 | GroupEvent groupEvent = null; | 827 | GroupEvent groupEvent = null; |
841 | - log.trace("GroupStoreIdMapListener: received groupid map event {}", | 828 | + StoredGroupEntry group = mapEvent.value(); |
829 | + log.trace("GroupStoreKeyMapListener: received groupid map event {}", | ||
842 | mapEvent.type()); | 830 | mapEvent.type()); |
843 | if (mapEvent.type() == EventuallyConsistentMapEvent.Type.PUT) { | 831 | if (mapEvent.type() == EventuallyConsistentMapEvent.Type.PUT) { |
844 | - log.trace("GroupIdMapListener: Received PUT event"); | 832 | + log.trace("GroupStoreKeyMapListener: Received PUT event"); |
833 | + // Update the group ID table | ||
834 | + getGroupIdTable(group.deviceId()).put(group.id(), group); | ||
845 | if (mapEvent.value().state() == Group.GroupState.ADDED) { | 835 | if (mapEvent.value().state() == Group.GroupState.ADDED) { |
846 | if (mapEvent.value().isGroupStateAddedFirstTime()) { | 836 | if (mapEvent.value().isGroupStateAddedFirstTime()) { |
847 | groupEvent = new GroupEvent(Type.GROUP_ADDED, | 837 | groupEvent = new GroupEvent(Type.GROUP_ADDED, |
848 | mapEvent.value()); | 838 | mapEvent.value()); |
849 | - log.trace("GroupIdMapListener: Received first time " | 839 | + log.trace("GroupStoreKeyMapListener: Received first time " |
850 | + "GROUP_ADDED state update"); | 840 | + "GROUP_ADDED state update"); |
851 | } else { | 841 | } else { |
852 | groupEvent = new GroupEvent(Type.GROUP_UPDATED, | 842 | groupEvent = new GroupEvent(Type.GROUP_UPDATED, |
853 | mapEvent.value()); | 843 | mapEvent.value()); |
854 | - log.trace("GroupIdMapListener: Received following " | 844 | + log.trace("GroupStoreKeyMapListener: Received following " |
855 | + "GROUP_ADDED state update"); | 845 | + "GROUP_ADDED state update"); |
856 | } | 846 | } |
857 | } | 847 | } |
858 | } else if (mapEvent.type() == EventuallyConsistentMapEvent.Type.REMOVE) { | 848 | } else if (mapEvent.type() == EventuallyConsistentMapEvent.Type.REMOVE) { |
859 | - log.trace("GroupIdMapListener: Received REMOVE event"); | 849 | + log.trace("GroupStoreKeyMapListener: Received REMOVE event"); |
860 | groupEvent = new GroupEvent(Type.GROUP_REMOVED, mapEvent.value()); | 850 | groupEvent = new GroupEvent(Type.GROUP_REMOVED, mapEvent.value()); |
851 | + // Remove the entry from the group ID table | ||
852 | + getGroupIdTable(group.deviceId()).remove(group.id(), group); | ||
861 | } | 853 | } |
862 | 854 | ||
863 | if (groupEvent != null) { | 855 | if (groupEvent != null) { | ... | ... |
-
Please register or login to post a comment