Saurav Das
Committed by Gerrit Code Review

In this commit:

    Removing dependence on hashing for unique groupkeys in ofdpa driver.
    Group-store no longer removes groups from store if a group-operation fails due to GROUP_EXISTS.
    Group-store also checks for unique group-id when given by app.
    Group-provider now logs warning before making call to core.

Change-Id: I4a1dcb887cb74cd6e245df0c82c90a50d8f3898a
...@@ -537,6 +537,19 @@ public class DistributedGroupStore ...@@ -537,6 +537,19 @@ public class DistributedGroupStore
537 // Get a new group identifier 537 // Get a new group identifier
538 id = new DefaultGroupId(getFreeGroupIdValue(groupDesc.deviceId())); 538 id = new DefaultGroupId(getFreeGroupIdValue(groupDesc.deviceId()));
539 } else { 539 } else {
540 + // we need to use the identifier passed in by caller, but check if
541 + // already used
542 + Group existing = getGroup(groupDesc.deviceId(),
543 + new DefaultGroupId(groupDesc.givenGroupId()));
544 + if (existing != null) {
545 + log.warn("Group already exists with the same id: 0x{} in dev:{} "
546 + + "but with different key: {} (request gkey: {})",
547 + Integer.toHexString(groupDesc.givenGroupId()),
548 + groupDesc.deviceId(),
549 + existing.appCookie(),
550 + groupDesc.appCookie());
551 + return;
552 + }
540 id = new DefaultGroupId(groupDesc.givenGroupId()); 553 id = new DefaultGroupId(groupDesc.givenGroupId());
541 } 554 }
542 // Create a group entry object 555 // Create a group entry object
...@@ -621,7 +634,8 @@ public class DistributedGroupStore ...@@ -621,7 +634,8 @@ public class DistributedGroupStore
621 // Check if a group is existing with the provided key 634 // Check if a group is existing with the provided key
622 Group oldGroup = getGroup(deviceId, oldAppCookie); 635 Group oldGroup = getGroup(deviceId, oldAppCookie);
623 if (oldGroup == null) { 636 if (oldGroup == null) {
624 - log.warn("updateGroupDescriptionInternal: Group not found...strange"); 637 + log.warn("updateGroupDescriptionInternal: Group not found...strange. "
638 + + "GroupKey:{} DeviceId:{}", oldAppCookie, deviceId);
625 return; 639 return;
626 } 640 }
627 641
...@@ -940,6 +954,19 @@ public class DistributedGroupStore ...@@ -940,6 +954,19 @@ public class DistributedGroupStore
940 log.warn("Current extraneous groups in device:{} are: {}", 954 log.warn("Current extraneous groups in device:{} are: {}",
941 deviceId, 955 deviceId,
942 getExtraneousGroups(deviceId)); 956 getExtraneousGroups(deviceId));
957 + if (operation.buckets().equals(existing.buckets())) {
958 + if (existing.state() == GroupState.PENDING_ADD) {
959 + log.info("GROUP_EXISTS: GroupID and Buckets match for group in pending "
960 + + "add state - moving to ADDED for group {} in device {}",
961 + existing.id(), deviceId);
962 + addOrUpdateGroupEntry(existing);
963 + return;
964 + } else {
965 + log.warn("GROUP EXISTS: Group ID matched but buckets did not. "
966 + + "Operation: {} Existing: {}", operation.buckets(),
967 + existing.buckets());
968 + }
969 + }
943 } 970 }
944 switch (operation.opType()) { 971 switch (operation.opType()) {
945 case ADD: 972 case ADD:
......
...@@ -36,6 +36,8 @@ import org.onosproject.net.group.GroupEvent; ...@@ -36,6 +36,8 @@ import org.onosproject.net.group.GroupEvent;
36 import org.onosproject.net.group.GroupKey; 36 import org.onosproject.net.group.GroupKey;
37 import org.onosproject.net.group.GroupListener; 37 import org.onosproject.net.group.GroupListener;
38 import org.onosproject.net.group.GroupService; 38 import org.onosproject.net.group.GroupService;
39 +import org.onosproject.store.service.AtomicCounter;
40 +import org.onosproject.store.service.StorageService;
39 import org.slf4j.Logger; 41 import org.slf4j.Logger;
40 42
41 import java.util.ArrayDeque; 43 import java.util.ArrayDeque;
...@@ -87,6 +89,7 @@ public class OFDPA2GroupHandler { ...@@ -87,6 +89,7 @@ public class OFDPA2GroupHandler {
87 private final Logger log = getLogger(getClass()); 89 private final Logger log = getLogger(getClass());
88 private ServiceDirectory serviceDirectory; 90 private ServiceDirectory serviceDirectory;
89 protected GroupService groupService; 91 protected GroupService groupService;
92 + protected StorageService storageService;
90 93
91 private DeviceId deviceId; 94 private DeviceId deviceId;
92 private FlowObjectiveStore flowObjectiveStore; 95 private FlowObjectiveStore flowObjectiveStore;
...@@ -96,7 +99,7 @@ public class OFDPA2GroupHandler { ...@@ -96,7 +99,7 @@ public class OFDPA2GroupHandler {
96 Executors.newScheduledThreadPool(2, groupedThreads("onos/pipeliner", "ofdpa2-%d")); 99 Executors.newScheduledThreadPool(2, groupedThreads("onos/pipeliner", "ofdpa2-%d"));
97 100
98 // index number for group creation 101 // index number for group creation
99 - private AtomicInteger l3VpnIndex = new AtomicInteger(0); 102 + private AtomicCounter nextIndex;
100 103
101 // local stores for port-vlan mapping 104 // local stores for port-vlan mapping
102 protected Map<PortNumber, VlanId> port2Vlan = new ConcurrentHashMap<>(); 105 protected Map<PortNumber, VlanId> port2Vlan = new ConcurrentHashMap<>();
...@@ -111,6 +114,11 @@ public class OFDPA2GroupHandler { ...@@ -111,6 +114,11 @@ public class OFDPA2GroupHandler {
111 this.flowObjectiveStore = context.store(); 114 this.flowObjectiveStore = context.store();
112 this.serviceDirectory = context.directory(); 115 this.serviceDirectory = context.directory();
113 this.groupService = serviceDirectory.get(GroupService.class); 116 this.groupService = serviceDirectory.get(GroupService.class);
117 + this.storageService = serviceDirectory.get(StorageService.class);
118 + this.nextIndex = storageService.atomicCounterBuilder()
119 + .withName("group-id-index-counter")
120 + .build()
121 + .asAtomicCounter();
114 122
115 pendingNextObjectives = CacheBuilder.newBuilder() 123 pendingNextObjectives = CacheBuilder.newBuilder()
116 .expireAfterWrite(20, TimeUnit.SECONDS) 124 .expireAfterWrite(20, TimeUnit.SECONDS)
...@@ -129,6 +137,10 @@ public class OFDPA2GroupHandler { ...@@ -129,6 +137,10 @@ public class OFDPA2GroupHandler {
129 groupService.addListener(new InnerGroupListener()); 137 groupService.addListener(new InnerGroupListener());
130 } 138 }
131 139
140 + //////////////////////////////////////
141 + // Group Creation
142 + //////////////////////////////////////
143 +
132 protected void addGroup(NextObjective nextObjective) { 144 protected void addGroup(NextObjective nextObjective) {
133 switch (nextObjective.type()) { 145 switch (nextObjective.type()) {
134 case SIMPLE: 146 case SIMPLE:
...@@ -213,26 +225,6 @@ public class OFDPA2GroupHandler { ...@@ -213,26 +225,6 @@ public class OFDPA2GroupHandler {
213 groupService.addGroup(groupInfo.innerGrpDesc); 225 groupService.addGroup(groupInfo.innerGrpDesc);
214 } 226 }
215 227
216 - private void updatePendingNextObjective(GroupKey key, OfdpaNextGroup value) {
217 - List<OfdpaNextGroup> nextList = new CopyOnWriteArrayList<OfdpaNextGroup>();
218 - nextList.add(value);
219 - List<OfdpaNextGroup> ret = pendingNextObjectives.asMap()
220 - .putIfAbsent(key, nextList);
221 - if (ret != null) {
222 - ret.add(value);
223 - }
224 - }
225 -
226 - private void updatePendingGroups(GroupKey gkey, GroupChainElem gce) {
227 - Set<GroupChainElem> gceSet = Collections.newSetFromMap(
228 - new ConcurrentHashMap<GroupChainElem, Boolean>());
229 - gceSet.add(gce);
230 - Set<GroupChainElem> retval = pendingGroups.putIfAbsent(gkey, gceSet);
231 - if (retval != null) {
232 - retval.add(gce);
233 - }
234 - }
235 -
236 /** 228 /**
237 * Creates a simple L2 Interface Group. 229 * Creates a simple L2 Interface Group.
238 * 230 *
...@@ -403,7 +395,7 @@ public class OFDPA2GroupHandler { ...@@ -403,7 +395,7 @@ public class OFDPA2GroupHandler {
403 395
404 // assemble information for ofdpa l2interface group 396 // assemble information for ofdpa l2interface group
405 int l2groupId = L2_INTERFACE_TYPE | (vlanid.toShort() << 16) | (int) portNum; 397 int l2groupId = L2_INTERFACE_TYPE | (vlanid.toShort() << 16) | (int) portNum;
406 - // a globally unique groupkey that is different for ports in the same devices 398 + // a globally unique groupkey that is different for ports in the same device,
407 // but different for the same portnumber on different devices. Also different 399 // but different for the same portnumber on different devices. Also different
408 // for the various group-types created out of the same next objective. 400 // for the various group-types created out of the same next objective.
409 int l2gk = l2InterfaceGroupKey(deviceId, vlanid, portNum); 401 int l2gk = l2InterfaceGroupKey(deviceId, vlanid, portNum);
...@@ -413,10 +405,10 @@ public class OFDPA2GroupHandler { ...@@ -413,10 +405,10 @@ public class OFDPA2GroupHandler {
413 GroupDescription outerGrpDesc = null; 405 GroupDescription outerGrpDesc = null;
414 if (mpls) { 406 if (mpls) {
415 // outer group is MPLSInteface 407 // outer group is MPLSInteface
416 - int mplsgroupId = MPLS_INTERFACE_TYPE | (int) portNum; 408 + int mplsInterfaceIndex = getNextAvailableIndex();
417 - // using mplsinterfacemask in groupkey to differentiate from l2interface 409 + int mplsgroupId = MPLS_INTERFACE_TYPE | (SUBTYPE_MASK & mplsInterfaceIndex);
418 - int mplsgk = MPLS_INTERFACE_TYPE | (SUBTYPE_MASK & (deviceId.hashCode() << 8 | (int) portNum)); 410 + final GroupKey mplsgroupkey = new DefaultGroupKey(
419 - final GroupKey mplsgroupkey = new DefaultGroupKey(OFDPA2Pipeline.appKryo.serialize(mplsgk)); 411 + OFDPA2Pipeline.appKryo.serialize(mplsInterfaceIndex));
420 outerTtb.group(new DefaultGroupId(l2groupId)); 412 outerTtb.group(new DefaultGroupId(l2groupId));
421 // create the mpls-interface group description to wait for the 413 // create the mpls-interface group description to wait for the
422 // l2 interface group to be processed 414 // l2 interface group to be processed
...@@ -435,11 +427,10 @@ public class OFDPA2GroupHandler { ...@@ -435,11 +427,10 @@ public class OFDPA2GroupHandler {
435 mplsgroupkey, nextId); 427 mplsgroupkey, nextId);
436 } else { 428 } else {
437 // outer group is L3Unicast 429 // outer group is L3Unicast
438 - int l3GroupIdHash = Objects.hash(srcMac, dstMac, portNum); 430 + int l3unicastIndex = getNextAvailableIndex();
439 - int l3groupId = L3_UNICAST_TYPE | (TYPE_MASK & l3GroupIdHash); 431 + int l3groupId = L3_UNICAST_TYPE | (TYPE_MASK & l3unicastIndex);
440 - int l3GroupKeyHash = Objects.hash(deviceId, srcMac, dstMac, portNum); 432 + final GroupKey l3groupkey = new DefaultGroupKey(
441 - int l3gk = L3_UNICAST_TYPE | (TYPE_MASK & l3GroupKeyHash); 433 + OFDPA2Pipeline.appKryo.serialize(l3unicastIndex));
442 - final GroupKey l3groupkey = new DefaultGroupKey(OFDPA2Pipeline.appKryo.serialize(l3gk));
443 outerTtb.group(new DefaultGroupId(l2groupId)); 434 outerTtb.group(new DefaultGroupId(l2groupId));
444 // create the l3unicast group description to wait for the 435 // create the l3unicast group description to wait for the
445 // l2 interface group to be processed 436 // l2 interface group to be processed
...@@ -558,7 +549,7 @@ public class OFDPA2GroupHandler { ...@@ -558,7 +549,7 @@ public class OFDPA2GroupHandler {
558 // assemble info for l2 flood group 549 // assemble info for l2 flood group
559 // since there can be only one flood group for a vlan, its index is always the same - 0 550 // since there can be only one flood group for a vlan, its index is always the same - 0
560 Integer l2floodgroupId = L2_FLOOD_TYPE | (vlanId.toShort() << 16); 551 Integer l2floodgroupId = L2_FLOOD_TYPE | (vlanId.toShort() << 16);
561 - int l2floodgk = L2_FLOOD_TYPE | nextObj.id() << 12; 552 + int l2floodgk = getNextAvailableIndex();
562 final GroupKey l2floodgroupkey = new DefaultGroupKey(OFDPA2Pipeline.appKryo.serialize(l2floodgk)); 553 final GroupKey l2floodgroupkey = new DefaultGroupKey(OFDPA2Pipeline.appKryo.serialize(l2floodgk));
563 // collection of group buckets pointing to all the l2 interface groups 554 // collection of group buckets pointing to all the l2 interface groups
564 List<GroupBucket> l2floodBuckets = new ArrayList<>(); 555 List<GroupBucket> l2floodBuckets = new ArrayList<>();
...@@ -633,8 +624,10 @@ public class OFDPA2GroupHandler { ...@@ -633,8 +624,10 @@ public class OFDPA2GroupHandler {
633 .createSelectGroupBucket(ttb.build()); 624 .createSelectGroupBucket(ttb.build());
634 l3ecmpGroupBuckets.add(sbucket); 625 l3ecmpGroupBuckets.add(sbucket);
635 } 626 }
636 - int l3ecmpGroupId = L3_ECMP_TYPE | nextObj.id() << 12; 627 + int l3ecmpIndex = getNextAvailableIndex();
637 - GroupKey l3ecmpGroupKey = new DefaultGroupKey(OFDPA2Pipeline.appKryo.serialize(l3ecmpGroupId)); 628 + int l3ecmpGroupId = L3_ECMP_TYPE | (TYPE_MASK & l3ecmpIndex);
629 + GroupKey l3ecmpGroupKey = new DefaultGroupKey(
630 + OFDPA2Pipeline.appKryo.serialize(l3ecmpIndex));
638 GroupDescription l3ecmpGroupDesc = 631 GroupDescription l3ecmpGroupDesc =
639 new DefaultGroupDescription( 632 new DefaultGroupDescription(
640 deviceId, 633 deviceId,
...@@ -742,9 +735,10 @@ public class OFDPA2GroupHandler { ...@@ -742,9 +735,10 @@ public class OFDPA2GroupHandler {
742 onelabelGroupInfo.outerGrpDesc.givenGroupId())); 735 onelabelGroupInfo.outerGrpDesc.givenGroupId()));
743 GroupBucket l3vpnGrpBkt = 736 GroupBucket l3vpnGrpBkt =
744 DefaultGroupBucket.createIndirectGroupBucket(l3vpnTtb.build()); 737 DefaultGroupBucket.createIndirectGroupBucket(l3vpnTtb.build());
745 - int l3vpngroupId = MPLS_L3VPN_SUBTYPE | l3VpnIndex.incrementAndGet(); 738 + int l3vpnIndex = getNextAvailableIndex();
746 - int l3vpngk = MPLS_L3VPN_SUBTYPE | nextObj.id() << 12 | l3VpnIndex.get(); 739 + int l3vpngroupId = MPLS_L3VPN_SUBTYPE | (SUBTYPE_MASK & l3vpnIndex);
747 - GroupKey l3vpngroupkey = new DefaultGroupKey(OFDPA2Pipeline.appKryo.serialize(l3vpngk)); 740 + GroupKey l3vpngroupkey = new DefaultGroupKey(
741 + OFDPA2Pipeline.appKryo.serialize(l3vpnIndex));
748 GroupDescription l3vpnGroupDesc = 742 GroupDescription l3vpnGroupDesc =
749 new DefaultGroupDescription( 743 new DefaultGroupDescription(
750 deviceId, 744 deviceId,
...@@ -783,6 +777,10 @@ public class OFDPA2GroupHandler { ...@@ -783,6 +777,10 @@ public class OFDPA2GroupHandler {
783 } 777 }
784 } 778 }
785 779
780 + //////////////////////////////////////
781 + // Group Editing
782 + //////////////////////////////////////
783 +
786 /** 784 /**
787 * Adds a bucket to the top level group of a group-chain, and creates the chain. 785 * Adds a bucket to the top level group of a group-chain, and creates the chain.
788 * 786 *
...@@ -954,6 +952,30 @@ public class OFDPA2GroupHandler { ...@@ -954,6 +952,30 @@ public class OFDPA2GroupHandler {
954 flowObjectiveStore.removeNextGroup(nextObjective.id()); 952 flowObjectiveStore.removeNextGroup(nextObjective.id());
955 } 953 }
956 954
955 + //////////////////////////////////////
956 + // Helper Methods and Classes
957 + //////////////////////////////////////
958 +
959 + private void updatePendingNextObjective(GroupKey key, OfdpaNextGroup value) {
960 + List<OfdpaNextGroup> nextList = new CopyOnWriteArrayList<OfdpaNextGroup>();
961 + nextList.add(value);
962 + List<OfdpaNextGroup> ret = pendingNextObjectives.asMap()
963 + .putIfAbsent(key, nextList);
964 + if (ret != null) {
965 + ret.add(value);
966 + }
967 + }
968 +
969 + private void updatePendingGroups(GroupKey gkey, GroupChainElem gce) {
970 + Set<GroupChainElem> gceSet = Collections.newSetFromMap(
971 + new ConcurrentHashMap<GroupChainElem, Boolean>());
972 + gceSet.add(gce);
973 + Set<GroupChainElem> retval = pendingGroups.putIfAbsent(gkey, gceSet);
974 + if (retval != null) {
975 + retval.add(gce);
976 + }
977 + }
978 +
957 /** 979 /**
958 * Processes next element of a group chain. Assumption is that if this 980 * Processes next element of a group chain. Assumption is that if this
959 * group points to another group, the latter has already been created 981 * group points to another group, the latter has already been created
...@@ -1002,6 +1024,17 @@ public class OFDPA2GroupHandler { ...@@ -1002,6 +1024,17 @@ public class OFDPA2GroupHandler {
1002 } 1024 }
1003 } 1025 }
1004 1026
1027 + private class InnerGroupListener implements GroupListener {
1028 + @Override
1029 + public void event(GroupEvent event) {
1030 + log.trace("received group event of type {}", event.type());
1031 + if (event.type() == GroupEvent.Type.GROUP_ADDED) {
1032 + GroupKey key = event.subject().appCookie();
1033 + processPendingGroupsOrNextObjectives(key, true);
1034 + }
1035 + }
1036 + }
1037 +
1005 private void processPendingGroupsOrNextObjectives(GroupKey key, boolean added) { 1038 private void processPendingGroupsOrNextObjectives(GroupKey key, boolean added) {
1006 //first check for group chain 1039 //first check for group chain
1007 Set<GroupChainElem> gceSet = pendingGroups.remove(key); 1040 Set<GroupChainElem> gceSet = pendingGroups.remove(key);
...@@ -1046,6 +1079,10 @@ public class OFDPA2GroupHandler { ...@@ -1046,6 +1079,10 @@ public class OFDPA2GroupHandler {
1046 ? null : ((VlanIdCriterion) criterion).vlanId(); 1079 ? null : ((VlanIdCriterion) criterion).vlanId();
1047 } 1080 }
1048 1081
1082 + private int getNextAvailableIndex() {
1083 + return (int) nextIndex.incrementAndGet();
1084 + }
1085 +
1049 /** 1086 /**
1050 * Returns a hash as the L2 Interface Group Key. 1087 * Returns a hash as the L2 Interface Group Key.
1051 * 1088 *
...@@ -1065,17 +1102,6 @@ public class OFDPA2GroupHandler { ...@@ -1065,17 +1102,6 @@ public class OFDPA2GroupHandler {
1065 return L2_INTERFACE_TYPE | (TYPE_MASK & hash << 6) | portLowerBits; 1102 return L2_INTERFACE_TYPE | (TYPE_MASK & hash << 6) | portLowerBits;
1066 } 1103 }
1067 1104
1068 - private class InnerGroupListener implements GroupListener {
1069 - @Override
1070 - public void event(GroupEvent event) {
1071 - log.trace("received group event of type {}", event.type());
1072 - if (event.type() == GroupEvent.Type.GROUP_ADDED) {
1073 - GroupKey key = event.subject().appCookie();
1074 - processPendingGroupsOrNextObjectives(key, true);
1075 - }
1076 - }
1077 - }
1078 -
1079 /** 1105 /**
1080 * Utility class for moving group information around. 1106 * Utility class for moving group information around.
1081 */ 1107 */
......
...@@ -1030,26 +1030,30 @@ public class OFDPA2Pipeline extends AbstractHandlerBehaviour implements Pipeline ...@@ -1030,26 +1030,30 @@ public class OFDPA2Pipeline extends AbstractHandlerBehaviour implements Pipeline
1030 obj.context().ifPresent(context -> context.onError(obj, error)); 1030 obj.context().ifPresent(context -> context.onError(obj, error));
1031 } 1031 }
1032 1032
1033 -
1034 @Override 1033 @Override
1035 public List<String> getNextMappings(NextGroup nextGroup) { 1034 public List<String> getNextMappings(NextGroup nextGroup) {
1036 List<String> mappings = new ArrayList<>(); 1035 List<String> mappings = new ArrayList<>();
1037 List<Deque<GroupKey>> gkeys = appKryo.deserialize(nextGroup.data()); 1036 List<Deque<GroupKey>> gkeys = appKryo.deserialize(nextGroup.data());
1038 for (Deque<GroupKey> gkd : gkeys) { 1037 for (Deque<GroupKey> gkd : gkeys) {
1039 Group lastGroup = null; 1038 Group lastGroup = null;
1040 - String gchain = ""; 1039 + StringBuffer gchain = new StringBuffer();
1041 for (GroupKey gk : gkd) { 1040 for (GroupKey gk : gkd) {
1042 Group g = groupService.getGroup(deviceId, gk); 1041 Group g = groupService.getGroup(deviceId, gk);
1043 - gchain += " 0x" + Integer.toHexString(g.id().id()) + " -->"; 1042 + if (g == null) {
1043 + gchain.append(" ERROR").append(" -->");
1044 + continue;
1045 + }
1046 + gchain.append(" 0x").append(Integer.toHexString(g.id().id()))
1047 + .append(" -->");
1044 lastGroup = g; 1048 lastGroup = g;
1045 } 1049 }
1046 // add port information for last group in group-chain 1050 // add port information for last group in group-chain
1047 for (Instruction i: lastGroup.buckets().buckets().get(0).treatment().allInstructions()) { 1051 for (Instruction i: lastGroup.buckets().buckets().get(0).treatment().allInstructions()) {
1048 if (i instanceof OutputInstruction) { 1052 if (i instanceof OutputInstruction) {
1049 - gchain += " port:" + ((OutputInstruction) i).port(); 1053 + gchain.append(" port:").append(((OutputInstruction) i).port());
1050 } 1054 }
1051 } 1055 }
1052 - mappings.add(gchain); 1056 + mappings.add(gchain.toString());
1053 } 1057 }
1054 return mappings; 1058 return mappings;
1055 } 1059 }
......
...@@ -337,11 +337,11 @@ public class OpenFlowGroupProvider extends AbstractProvider implements GroupProv ...@@ -337,11 +337,11 @@ public class OpenFlowGroupProvider extends AbstractProvider implements GroupProv
337 GroupMsgErrorCode.values()[(code.ordinal())]; 337 GroupMsgErrorCode.values()[(code.ordinal())];
338 GroupOperation failedOperation = GroupOperation 338 GroupOperation failedOperation = GroupOperation
339 .createFailedGroupOperation(operation, failureCode); 339 .createFailedGroupOperation(operation, failureCode);
340 + log.warn("Received a group mod error {}", msg);
340 providerService.groupOperationFailed(deviceId, 341 providerService.groupOperationFailed(deviceId,
341 failedOperation); 342 failedOperation);
342 pendingGroupOperations.remove(pendingGroupId); 343 pendingGroupOperations.remove(pendingGroupId);
343 pendingXidMaps.remove(pendingGroupId); 344 pendingXidMaps.remove(pendingGroupId);
344 - log.warn("Received a group mod error {}", msg);
345 } else { 345 } else {
346 log.error("Cannot find pending group operation with group ID: {}", 346 log.error("Cannot find pending group operation with group ID: {}",
347 pendingGroupId); 347 pendingGroupId);
......