Srikanth Vavilapalli
Committed by Ray Milkey

ONOS-1433: Avoid two EC maps for same data with different keys

Change-Id: I2377507e52fa1942cbea247c2f9d08d8f0587f22
...@@ -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) {
......