alshabib
Committed by Gerrit Code Review

adding group garbage collection functionality

If a group has a reference count of zero for more than
a configurable timeout, it is garbage collected.

This feature can be deactivated by component config.

Change-Id: I254d62a90ef7ac8d2ce2f406b67957455a5bf4d0
...@@ -35,6 +35,7 @@ public class DefaultGroup extends DefaultGroupDescription ...@@ -35,6 +35,7 @@ public class DefaultGroup extends DefaultGroupDescription
35 private long bytes; 35 private long bytes;
36 private long referenceCount; 36 private long referenceCount;
37 private GroupId id; 37 private GroupId id;
38 + private int age;
38 39
39 /** 40 /**
40 * Initializes default values. 41 * Initializes default values.
...@@ -48,6 +49,7 @@ public class DefaultGroup extends DefaultGroupDescription ...@@ -48,6 +49,7 @@ public class DefaultGroup extends DefaultGroupDescription
48 packets = 0; 49 packets = 0;
49 bytes = 0; 50 bytes = 0;
50 referenceCount = 0; 51 referenceCount = 0;
52 + age = 0;
51 } 53 }
52 54
53 /** 55 /**
...@@ -128,6 +130,11 @@ public class DefaultGroup extends DefaultGroupDescription ...@@ -128,6 +130,11 @@ public class DefaultGroup extends DefaultGroupDescription
128 return this.bytes; 130 return this.bytes;
129 } 131 }
130 132
133 + @Override
134 + public int age() {
135 + return age;
136 + }
137 +
131 /** 138 /**
132 * Sets the new state for this entry. 139 * Sets the new state for this entry.
133 * 140 *
...@@ -171,6 +178,11 @@ public class DefaultGroup extends DefaultGroupDescription ...@@ -171,6 +178,11 @@ public class DefaultGroup extends DefaultGroupDescription
171 @Override 178 @Override
172 public void setReferenceCount(long referenceCount) { 179 public void setReferenceCount(long referenceCount) {
173 this.referenceCount = referenceCount; 180 this.referenceCount = referenceCount;
181 + if (referenceCount == 0) {
182 + age++;
183 + } else {
184 + age = 0;
185 + }
174 } 186 }
175 187
176 @Override 188 @Override
...@@ -214,6 +226,7 @@ public class DefaultGroup extends DefaultGroupDescription ...@@ -214,6 +226,7 @@ public class DefaultGroup extends DefaultGroupDescription
214 .add("description", super.toString()) 226 .add("description", super.toString())
215 .add("groupid", id) 227 .add("groupid", id)
216 .add("state", state) 228 .add("state", state)
229 + .add("age", age)
217 .toString(); 230 .toString();
218 } 231 }
219 232
......
...@@ -96,4 +96,12 @@ public interface Group extends GroupDescription { ...@@ -96,4 +96,12 @@ public interface Group extends GroupDescription {
96 * @return number of flow rules or other groups pointing to this group 96 * @return number of flow rules or other groups pointing to this group
97 */ 97 */
98 long referenceCount(); 98 long referenceCount();
99 +
100 + /**
101 + * Obtains the age of a group. The age reflects the number of polling rounds
102 + * the group has had a reference count of zero.
103 + *
104 + * @return the age of the group as an integer
105 + */
106 + int age();
99 } 107 }
......
...@@ -19,15 +19,17 @@ import com.google.common.collect.FluentIterable; ...@@ -19,15 +19,17 @@ import com.google.common.collect.FluentIterable;
19 import com.google.common.collect.ImmutableSet; 19 import com.google.common.collect.ImmutableSet;
20 import com.google.common.collect.Iterables; 20 import com.google.common.collect.Iterables;
21 import com.google.common.collect.Sets; 21 import com.google.common.collect.Sets;
22 -
23 import org.apache.felix.scr.annotations.Activate; 22 import org.apache.felix.scr.annotations.Activate;
24 import org.apache.felix.scr.annotations.Component; 23 import org.apache.felix.scr.annotations.Component;
25 import org.apache.felix.scr.annotations.Deactivate; 24 import org.apache.felix.scr.annotations.Deactivate;
25 +import org.apache.felix.scr.annotations.Modified;
26 +import org.apache.felix.scr.annotations.Property;
26 import org.apache.felix.scr.annotations.Reference; 27 import org.apache.felix.scr.annotations.Reference;
27 import org.apache.felix.scr.annotations.ReferenceCardinality; 28 import org.apache.felix.scr.annotations.ReferenceCardinality;
28 import org.apache.felix.scr.annotations.Service; 29 import org.apache.felix.scr.annotations.Service;
29 import org.onlab.util.KryoNamespace; 30 import org.onlab.util.KryoNamespace;
30 import org.onlab.util.NewConcurrentHashMap; 31 import org.onlab.util.NewConcurrentHashMap;
32 +import org.onosproject.cfg.ComponentConfigService;
31 import org.onosproject.cluster.ClusterService; 33 import org.onosproject.cluster.ClusterService;
32 import org.onosproject.cluster.NodeId; 34 import org.onosproject.cluster.NodeId;
33 import org.onosproject.core.DefaultGroupId; 35 import org.onosproject.core.DefaultGroupId;
...@@ -54,19 +56,21 @@ import org.onosproject.net.group.StoredGroupBucketEntry; ...@@ -54,19 +56,21 @@ import org.onosproject.net.group.StoredGroupBucketEntry;
54 import org.onosproject.net.group.StoredGroupEntry; 56 import org.onosproject.net.group.StoredGroupEntry;
55 import org.onosproject.store.AbstractStore; 57 import org.onosproject.store.AbstractStore;
56 import org.onosproject.store.cluster.messaging.ClusterCommunicationService; 58 import org.onosproject.store.cluster.messaging.ClusterCommunicationService;
57 -import org.onosproject.store.service.MultiValuedTimestamp;
58 import org.onosproject.store.serializers.KryoNamespaces; 59 import org.onosproject.store.serializers.KryoNamespaces;
59 import org.onosproject.store.service.ConsistentMap; 60 import org.onosproject.store.service.ConsistentMap;
60 import org.onosproject.store.service.MapEvent; 61 import org.onosproject.store.service.MapEvent;
61 import org.onosproject.store.service.MapEventListener; 62 import org.onosproject.store.service.MapEventListener;
63 +import org.onosproject.store.service.MultiValuedTimestamp;
62 import org.onosproject.store.service.Serializer; 64 import org.onosproject.store.service.Serializer;
63 import org.onosproject.store.service.StorageService; 65 import org.onosproject.store.service.StorageService;
64 import org.onosproject.store.service.Versioned; 66 import org.onosproject.store.service.Versioned;
67 +import org.osgi.service.component.ComponentContext;
65 import org.slf4j.Logger; 68 import org.slf4j.Logger;
66 69
67 import java.util.ArrayList; 70 import java.util.ArrayList;
68 import java.util.Collection; 71 import java.util.Collection;
69 import java.util.Collections; 72 import java.util.Collections;
73 +import java.util.Dictionary;
70 import java.util.HashMap; 74 import java.util.HashMap;
71 import java.util.HashSet; 75 import java.util.HashSet;
72 import java.util.Iterator; 76 import java.util.Iterator;
...@@ -75,6 +79,7 @@ import java.util.Map; ...@@ -75,6 +79,7 @@ import java.util.Map;
75 import java.util.Map.Entry; 79 import java.util.Map.Entry;
76 import java.util.Objects; 80 import java.util.Objects;
77 import java.util.Optional; 81 import java.util.Optional;
82 +import java.util.Properties;
78 import java.util.Set; 83 import java.util.Set;
79 import java.util.concurrent.ConcurrentHashMap; 84 import java.util.concurrent.ConcurrentHashMap;
80 import java.util.concurrent.ConcurrentMap; 85 import java.util.concurrent.ConcurrentMap;
...@@ -83,7 +88,9 @@ import java.util.concurrent.Executors; ...@@ -83,7 +88,9 @@ import java.util.concurrent.Executors;
83 import java.util.concurrent.atomic.AtomicInteger; 88 import java.util.concurrent.atomic.AtomicInteger;
84 import java.util.stream.Collectors; 89 import java.util.stream.Collectors;
85 90
91 +import static com.google.common.base.Strings.isNullOrEmpty;
86 import static org.apache.commons.lang3.concurrent.ConcurrentUtils.createIfAbsentUnchecked; 92 import static org.apache.commons.lang3.concurrent.ConcurrentUtils.createIfAbsentUnchecked;
93 +import static org.onlab.util.Tools.get;
87 import static org.onlab.util.Tools.groupedThreads; 94 import static org.onlab.util.Tools.groupedThreads;
88 import static org.slf4j.LoggerFactory.getLogger; 95 import static org.slf4j.LoggerFactory.getLogger;
89 96
...@@ -99,6 +106,9 @@ public class DistributedGroupStore ...@@ -99,6 +106,9 @@ public class DistributedGroupStore
99 106
100 private final Logger log = getLogger(getClass()); 107 private final Logger log = getLogger(getClass());
101 108
109 + private static final boolean GARBAGE_COLLECT = false;
110 + private static final int GC_THRESH = 6;
111 +
102 private final int dummyId = 0xffffffff; 112 private final int dummyId = 0xffffffff;
103 private final GroupId dummyGroupId = new DefaultGroupId(dummyId); 113 private final GroupId dummyGroupId = new DefaultGroupId(dummyId);
104 114
...@@ -114,14 +124,17 @@ public class DistributedGroupStore ...@@ -114,14 +124,17 @@ public class DistributedGroupStore
114 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) 124 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
115 protected MastershipService mastershipService; 125 protected MastershipService mastershipService;
116 126
127 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
128 + protected ComponentConfigService cfgService;
129 +
117 // Per device group table with (device id + app cookie) as key 130 // Per device group table with (device id + app cookie) as key
118 private ConsistentMap<GroupStoreKeyMapKey, 131 private ConsistentMap<GroupStoreKeyMapKey,
119 - StoredGroupEntry> groupStoreEntriesByKey = null; 132 + StoredGroupEntry> groupStoreEntriesByKey = null;
120 // Per device group table with (device id + group id) as key 133 // Per device group table with (device id + group id) as key
121 private final ConcurrentMap<DeviceId, ConcurrentMap<GroupId, StoredGroupEntry>> 134 private final ConcurrentMap<DeviceId, ConcurrentMap<GroupId, StoredGroupEntry>>
122 - groupEntriesById = new ConcurrentHashMap<>(); 135 + groupEntriesById = new ConcurrentHashMap<>();
123 private ConsistentMap<GroupStoreKeyMapKey, 136 private ConsistentMap<GroupStoreKeyMapKey,
124 - StoredGroupEntry> auditPendingReqQueue = null; 137 + StoredGroupEntry> auditPendingReqQueue = null;
125 private final ConcurrentMap<DeviceId, ConcurrentMap<GroupId, Group>> 138 private final ConcurrentMap<DeviceId, ConcurrentMap<GroupId, Group>>
126 extraneousGroupEntriesById = new ConcurrentHashMap<>(); 139 extraneousGroupEntriesById = new ConcurrentHashMap<>();
127 private ExecutorService messageHandlingExecutor; 140 private ExecutorService messageHandlingExecutor;
...@@ -135,27 +148,37 @@ public class DistributedGroupStore ...@@ -135,27 +148,37 @@ public class DistributedGroupStore
135 148
136 private KryoNamespace clusterMsgSerializer; 149 private KryoNamespace clusterMsgSerializer;
137 150
151 + @Property(name = "garbageCollect", boolValue = GARBAGE_COLLECT,
152 + label = "Enable group garbage collection")
153 + private boolean garbageCollect = GARBAGE_COLLECT;
154 +
155 + @Property(name = "gcThresh", intValue = GC_THRESH,
156 + label = "Number of rounds for group garbage collection")
157 + private int gcThresh = GC_THRESH;
158 +
159 +
138 @Activate 160 @Activate
139 public void activate() { 161 public void activate() {
162 + cfgService.registerProperties(getClass());
140 kryoBuilder = new KryoNamespace.Builder() 163 kryoBuilder = new KryoNamespace.Builder()
141 - .register(KryoNamespaces.API) 164 + .register(KryoNamespaces.API)
142 - .register(DefaultGroup.class, 165 + .register(DefaultGroup.class,
143 - DefaultGroupBucket.class, 166 + DefaultGroupBucket.class,
144 - DefaultGroupDescription.class, 167 + DefaultGroupDescription.class,
145 - DefaultGroupKey.class, 168 + DefaultGroupKey.class,
146 - GroupDescription.Type.class, 169 + GroupDescription.Type.class,
147 - Group.GroupState.class, 170 + Group.GroupState.class,
148 - GroupBuckets.class, 171 + GroupBuckets.class,
149 - DefaultGroupId.class, 172 + DefaultGroupId.class,
150 - GroupStoreMessage.class, 173 + GroupStoreMessage.class,
151 - GroupStoreMessage.Type.class, 174 + GroupStoreMessage.Type.class,
152 - UpdateType.class, 175 + UpdateType.class,
153 - GroupStoreMessageSubjects.class, 176 + GroupStoreMessageSubjects.class,
154 - MultiValuedTimestamp.class, 177 + MultiValuedTimestamp.class,
155 - GroupStoreKeyMapKey.class, 178 + GroupStoreKeyMapKey.class,
156 - GroupStoreIdMapKey.class, 179 + GroupStoreIdMapKey.class,
157 - GroupStoreMapKey.class 180 + GroupStoreMapKey.class
158 - ); 181 + );
159 182
160 clusterMsgSerializer = kryoBuilder.build(); 183 clusterMsgSerializer = kryoBuilder.build();
161 184
...@@ -165,9 +188,9 @@ public class DistributedGroupStore ...@@ -165,9 +188,9 @@ public class DistributedGroupStore
165 "message-handlers")); 188 "message-handlers"));
166 189
167 clusterCommunicator.addSubscriber(GroupStoreMessageSubjects.REMOTE_GROUP_OP_REQUEST, 190 clusterCommunicator.addSubscriber(GroupStoreMessageSubjects.REMOTE_GROUP_OP_REQUEST,
168 - clusterMsgSerializer::deserialize, 191 + clusterMsgSerializer::deserialize,
169 - this::process, 192 + this::process,
170 - messageHandlingExecutor); 193 + messageHandlingExecutor);
171 194
172 log.debug("Creating Consistent map onos-group-store-keymap"); 195 log.debug("Creating Consistent map onos-group-store-keymap");
173 196
...@@ -193,19 +216,36 @@ public class DistributedGroupStore ...@@ -193,19 +216,36 @@ public class DistributedGroupStore
193 216
194 @Deactivate 217 @Deactivate
195 public void deactivate() { 218 public void deactivate() {
219 + cfgService.unregisterProperties(getClass(), false);
196 clusterCommunicator.removeSubscriber(GroupStoreMessageSubjects.REMOTE_GROUP_OP_REQUEST); 220 clusterCommunicator.removeSubscriber(GroupStoreMessageSubjects.REMOTE_GROUP_OP_REQUEST);
197 groupStoreEntriesByKey.destroy(); 221 groupStoreEntriesByKey.destroy();
198 auditPendingReqQueue.destroy(); 222 auditPendingReqQueue.destroy();
199 log.info("Stopped"); 223 log.info("Stopped");
200 } 224 }
201 225
226 + @Modified
227 + public void modified(ComponentContext context) {
228 + Dictionary<?, ?> properties = context != null ? context.getProperties() : new Properties();
229 +
230 + try {
231 + String s = get(properties, "garbageCollect");
232 + garbageCollect = isNullOrEmpty(s) ? GARBAGE_COLLECT : Boolean.parseBoolean(s.trim());
233 +
234 + s = get(properties, "gcThresh");
235 + gcThresh = isNullOrEmpty(s) ? GC_THRESH : Integer.parseInt(s.trim());
236 + } catch (Exception e) {
237 + gcThresh = GC_THRESH;
238 + garbageCollect = GARBAGE_COLLECT;
239 + }
240 + }
241 +
202 private static NewConcurrentHashMap<GroupId, Group> 242 private static NewConcurrentHashMap<GroupId, Group>
203 - lazyEmptyExtraneousGroupIdTable() { 243 + lazyEmptyExtraneousGroupIdTable() {
204 return NewConcurrentHashMap.<GroupId, Group>ifNeeded(); 244 return NewConcurrentHashMap.<GroupId, Group>ifNeeded();
205 } 245 }
206 246
207 private static NewConcurrentHashMap<GroupId, StoredGroupEntry> 247 private static NewConcurrentHashMap<GroupId, StoredGroupEntry>
208 - lazyEmptyGroupIdTable() { 248 + lazyEmptyGroupIdTable() {
209 return NewConcurrentHashMap.<GroupId, StoredGroupEntry>ifNeeded(); 249 return NewConcurrentHashMap.<GroupId, StoredGroupEntry>ifNeeded();
210 } 250 }
211 251
...@@ -215,7 +255,7 @@ public class DistributedGroupStore ...@@ -215,7 +255,7 @@ public class DistributedGroupStore
215 * @return Map representing group key table. 255 * @return Map representing group key table.
216 */ 256 */
217 private Map<GroupStoreKeyMapKey, StoredGroupEntry> 257 private Map<GroupStoreKeyMapKey, StoredGroupEntry>
218 - getGroupStoreKeyMap() { 258 + getGroupStoreKeyMap() {
219 return groupStoreEntriesByKey.asJavaMap(); 259 return groupStoreEntriesByKey.asJavaMap();
220 } 260 }
221 261
...@@ -236,7 +276,7 @@ public class DistributedGroupStore ...@@ -236,7 +276,7 @@ public class DistributedGroupStore
236 * @return Map representing group key table. 276 * @return Map representing group key table.
237 */ 277 */
238 private Map<GroupStoreKeyMapKey, StoredGroupEntry> 278 private Map<GroupStoreKeyMapKey, StoredGroupEntry>
239 - getPendingGroupKeyTable() { 279 + getPendingGroupKeyTable() {
240 return auditPendingReqQueue.asJavaMap(); 280 return auditPendingReqQueue.asJavaMap();
241 } 281 }
242 282
...@@ -261,14 +301,13 @@ public class DistributedGroupStore ...@@ -261,14 +301,13 @@ public class DistributedGroupStore
261 @Override 301 @Override
262 public int getGroupCount(DeviceId deviceId) { 302 public int getGroupCount(DeviceId deviceId) {
263 return (getGroups(deviceId) != null) ? 303 return (getGroups(deviceId) != null) ?
264 - Iterables.size(getGroups(deviceId)) : 0; 304 + Iterables.size(getGroups(deviceId)) : 0;
265 } 305 }
266 306
267 /** 307 /**
268 * Returns the groups associated with a device. 308 * Returns the groups associated with a device.
269 * 309 *
270 * @param deviceId the device ID 310 * @param deviceId the device ID
271 - *
272 * @return the group entries 311 * @return the group entries
273 */ 312 */
274 @Override 313 @Override
...@@ -294,9 +333,8 @@ public class DistributedGroupStore ...@@ -294,9 +333,8 @@ public class DistributedGroupStore
294 /** 333 /**
295 * Returns the stored group entry. 334 * Returns the stored group entry.
296 * 335 *
297 - * @param deviceId the device ID 336 + * @param deviceId the device ID
298 * @param appCookie the group key 337 * @param appCookie the group key
299 - *
300 * @return a group associated with the key 338 * @return a group associated with the key
301 */ 339 */
302 @Override 340 @Override
...@@ -365,8 +403,8 @@ public class DistributedGroupStore ...@@ -365,8 +403,8 @@ public class DistributedGroupStore
365 groupDesc.deviceId()); 403 groupDesc.deviceId());
366 if (mastershipService.getMasterFor(groupDesc.deviceId()) == null) { 404 if (mastershipService.getMasterFor(groupDesc.deviceId()) == null) {
367 log.error("No Master for device {}..." 405 log.error("No Master for device {}..."
368 - + "Can not perform add group operation", 406 + + "Can not perform add group operation",
369 - groupDesc.deviceId()); 407 + groupDesc.deviceId());
370 //TODO: Send Group operation failure event 408 //TODO: Send Group operation failure event
371 return; 409 return;
372 } 410 }
...@@ -375,19 +413,20 @@ public class DistributedGroupStore ...@@ -375,19 +413,20 @@ public class DistributedGroupStore
375 groupDesc); 413 groupDesc);
376 414
377 clusterCommunicator.unicast(groupOp, 415 clusterCommunicator.unicast(groupOp,
378 - GroupStoreMessageSubjects.REMOTE_GROUP_OP_REQUEST, 416 + GroupStoreMessageSubjects.REMOTE_GROUP_OP_REQUEST,
379 - clusterMsgSerializer::serialize, 417 + clusterMsgSerializer::serialize,
380 - mastershipService.getMasterFor(groupDesc.deviceId())).whenComplete((result, error) -> { 418 + mastershipService.getMasterFor(groupDesc.deviceId()))
419 + .whenComplete((result, error) -> {
381 if (error != null) { 420 if (error != null) {
382 log.warn("Failed to send request to master: {} to {}", 421 log.warn("Failed to send request to master: {} to {}",
383 - groupOp, 422 + groupOp,
384 - mastershipService.getMasterFor(groupDesc.deviceId())); 423 + mastershipService.getMasterFor(groupDesc.deviceId()));
385 //TODO: Send Group operation failure event 424 //TODO: Send Group operation failure event
386 } else { 425 } else {
387 log.debug("Sent Group operation request for device {} " 426 log.debug("Sent Group operation request for device {} "
388 - + "to remote MASTER {}", 427 + + "to remote MASTER {}",
389 - groupDesc.deviceId(), 428 + groupDesc.deviceId(),
390 - mastershipService.getMasterFor(groupDesc.deviceId())); 429 + mastershipService.getMasterFor(groupDesc.deviceId()));
391 } 430 }
392 }); 431 });
393 return; 432 return;
...@@ -415,7 +454,7 @@ public class DistributedGroupStore ...@@ -415,7 +454,7 @@ public class DistributedGroupStore
415 return null; 454 return null;
416 } 455 }
417 456
418 - for (Group extraneousGroup:extraneousMap.values()) { 457 + for (Group extraneousGroup : extraneousMap.values()) {
419 if (extraneousGroup.buckets().equals(buckets)) { 458 if (extraneousGroup.buckets().equals(buckets)) {
420 return extraneousGroup; 459 return extraneousGroup;
421 } 460 }
...@@ -434,7 +473,7 @@ public class DistributedGroupStore ...@@ -434,7 +473,7 @@ public class DistributedGroupStore
434 // Add this group description to pending group key table 473 // Add this group description to pending group key table
435 // Create a group entry object with Dummy Group ID 474 // Create a group entry object with Dummy Group ID
436 log.debug("storeGroupDescriptionInternal: Device {} AUDIT pending...Queuing Group ADD request", 475 log.debug("storeGroupDescriptionInternal: Device {} AUDIT pending...Queuing Group ADD request",
437 - groupDesc.deviceId()); 476 + groupDesc.deviceId());
438 StoredGroupEntry group = new DefaultGroup(dummyGroupId, groupDesc); 477 StoredGroupEntry group = new DefaultGroup(dummyGroupId, groupDesc);
439 group.setState(GroupState.WAITING_AUDIT_COMPLETE); 478 group.setState(GroupState.WAITING_AUDIT_COMPLETE);
440 Map<GroupStoreKeyMapKey, StoredGroupEntry> pendingKeyTable = 479 Map<GroupStoreKeyMapKey, StoredGroupEntry> pendingKeyTable =
...@@ -449,10 +488,10 @@ public class DistributedGroupStore ...@@ -449,10 +488,10 @@ public class DistributedGroupStore
449 if (groupDesc.givenGroupId() != null) { 488 if (groupDesc.givenGroupId() != null) {
450 //Check if there is a extraneous group existing with the same Id 489 //Check if there is a extraneous group existing with the same Id
451 matchingExtraneousGroup = getMatchingExtraneousGroupbyId( 490 matchingExtraneousGroup = getMatchingExtraneousGroupbyId(
452 - groupDesc.deviceId(), groupDesc.givenGroupId()); 491 + groupDesc.deviceId(), groupDesc.givenGroupId());
453 if (matchingExtraneousGroup != null) { 492 if (matchingExtraneousGroup != null) {
454 log.debug("storeGroupDescriptionInternal: Matching extraneous group " 493 log.debug("storeGroupDescriptionInternal: Matching extraneous group "
455 - + "found in Device {} for group id 0x{}", 494 + + "found in Device {} for group id 0x{}",
456 groupDesc.deviceId(), 495 groupDesc.deviceId(),
457 Integer.toHexString(groupDesc.givenGroupId())); 496 Integer.toHexString(groupDesc.givenGroupId()));
458 //Check if the group buckets matches with user provided buckets 497 //Check if the group buckets matches with user provided buckets
...@@ -460,19 +499,19 @@ public class DistributedGroupStore ...@@ -460,19 +499,19 @@ public class DistributedGroupStore
460 //Group is already existing with the same buckets and Id 499 //Group is already existing with the same buckets and Id
461 // Create a group entry object 500 // Create a group entry object
462 log.debug("storeGroupDescriptionInternal: Buckets also matching " 501 log.debug("storeGroupDescriptionInternal: Buckets also matching "
463 - + "in Device {} for group id 0x{}", 502 + + "in Device {} for group id 0x{}",
464 groupDesc.deviceId(), 503 groupDesc.deviceId(),
465 Integer.toHexString(groupDesc.givenGroupId())); 504 Integer.toHexString(groupDesc.givenGroupId()));
466 StoredGroupEntry group = new DefaultGroup( 505 StoredGroupEntry group = new DefaultGroup(
467 - matchingExtraneousGroup.id(), groupDesc); 506 + matchingExtraneousGroup.id(), groupDesc);
468 // Insert the newly created group entry into key and id maps 507 // Insert the newly created group entry into key and id maps
469 getGroupStoreKeyMap(). 508 getGroupStoreKeyMap().
470 - put(new GroupStoreKeyMapKey(groupDesc.deviceId(), 509 + put(new GroupStoreKeyMapKey(groupDesc.deviceId(),
471 - groupDesc.appCookie()), group); 510 + groupDesc.appCookie()), group);
472 // Ensure it also inserted into group id based table to 511 // Ensure it also inserted into group id based table to
473 // avoid any chances of duplication in group id generation 512 // avoid any chances of duplication in group id generation
474 getGroupIdTable(groupDesc.deviceId()). 513 getGroupIdTable(groupDesc.deviceId()).
475 - put(matchingExtraneousGroup.id(), group); 514 + put(matchingExtraneousGroup.id(), group);
476 addOrUpdateGroupEntry(matchingExtraneousGroup); 515 addOrUpdateGroupEntry(matchingExtraneousGroup);
477 removeExtraneousGroupEntry(matchingExtraneousGroup); 516 removeExtraneousGroupEntry(matchingExtraneousGroup);
478 return; 517 return;
...@@ -480,22 +519,22 @@ public class DistributedGroupStore ...@@ -480,22 +519,22 @@ public class DistributedGroupStore
480 //Group buckets are not matching. Update group 519 //Group buckets are not matching. Update group
481 //with user provided buckets. 520 //with user provided buckets.
482 log.debug("storeGroupDescriptionInternal: Buckets are not " 521 log.debug("storeGroupDescriptionInternal: Buckets are not "
483 - + "matching in Device {} for group id 0x{}", 522 + + "matching in Device {} for group id 0x{}",
484 groupDesc.deviceId(), 523 groupDesc.deviceId(),
485 Integer.toHexString(groupDesc.givenGroupId())); 524 Integer.toHexString(groupDesc.givenGroupId()));
486 StoredGroupEntry modifiedGroup = new DefaultGroup( 525 StoredGroupEntry modifiedGroup = new DefaultGroup(
487 - matchingExtraneousGroup.id(), groupDesc); 526 + matchingExtraneousGroup.id(), groupDesc);
488 modifiedGroup.setState(GroupState.PENDING_UPDATE); 527 modifiedGroup.setState(GroupState.PENDING_UPDATE);
489 getGroupStoreKeyMap(). 528 getGroupStoreKeyMap().
490 - put(new GroupStoreKeyMapKey(groupDesc.deviceId(), 529 + put(new GroupStoreKeyMapKey(groupDesc.deviceId(),
491 - groupDesc.appCookie()), modifiedGroup); 530 + groupDesc.appCookie()), modifiedGroup);
492 // Ensure it also inserted into group id based table to 531 // Ensure it also inserted into group id based table to
493 // avoid any chances of duplication in group id generation 532 // avoid any chances of duplication in group id generation
494 getGroupIdTable(groupDesc.deviceId()). 533 getGroupIdTable(groupDesc.deviceId()).
495 - put(matchingExtraneousGroup.id(), modifiedGroup); 534 + put(matchingExtraneousGroup.id(), modifiedGroup);
496 removeExtraneousGroupEntry(matchingExtraneousGroup); 535 removeExtraneousGroupEntry(matchingExtraneousGroup);
497 log.debug("storeGroupDescriptionInternal: Triggering Group " 536 log.debug("storeGroupDescriptionInternal: Triggering Group "
498 - + "UPDATE request for {} in device {}", 537 + + "UPDATE request for {} in device {}",
499 matchingExtraneousGroup.id(), 538 matchingExtraneousGroup.id(),
500 groupDesc.deviceId()); 539 groupDesc.deviceId());
501 notifyDelegate(new GroupEvent(Type.GROUP_UPDATE_REQUESTED, modifiedGroup)); 540 notifyDelegate(new GroupEvent(Type.GROUP_UPDATE_REQUESTED, modifiedGroup));
...@@ -505,7 +544,7 @@ public class DistributedGroupStore ...@@ -505,7 +544,7 @@ public class DistributedGroupStore
505 } else { 544 } else {
506 //Check if there is an extraneous group with user provided buckets 545 //Check if there is an extraneous group with user provided buckets
507 matchingExtraneousGroup = getMatchingExtraneousGroupbyBuckets( 546 matchingExtraneousGroup = getMatchingExtraneousGroupbyBuckets(
508 - groupDesc.deviceId(), groupDesc.buckets()); 547 + groupDesc.deviceId(), groupDesc.buckets());
509 if (matchingExtraneousGroup != null) { 548 if (matchingExtraneousGroup != null) {
510 //Group is already existing with the same buckets. 549 //Group is already existing with the same buckets.
511 //So reuse this group. 550 //So reuse this group.
...@@ -513,15 +552,15 @@ public class DistributedGroupStore ...@@ -513,15 +552,15 @@ public class DistributedGroupStore
513 groupDesc.deviceId()); 552 groupDesc.deviceId());
514 //Create a group entry object 553 //Create a group entry object
515 StoredGroupEntry group = new DefaultGroup( 554 StoredGroupEntry group = new DefaultGroup(
516 - matchingExtraneousGroup.id(), groupDesc); 555 + matchingExtraneousGroup.id(), groupDesc);
517 // Insert the newly created group entry into key and id maps 556 // Insert the newly created group entry into key and id maps
518 getGroupStoreKeyMap(). 557 getGroupStoreKeyMap().
519 - put(new GroupStoreKeyMapKey(groupDesc.deviceId(), 558 + put(new GroupStoreKeyMapKey(groupDesc.deviceId(),
520 - groupDesc.appCookie()), group); 559 + groupDesc.appCookie()), group);
521 // Ensure it also inserted into group id based table to 560 // Ensure it also inserted into group id based table to
522 // avoid any chances of duplication in group id generation 561 // avoid any chances of duplication in group id generation
523 getGroupIdTable(groupDesc.deviceId()). 562 getGroupIdTable(groupDesc.deviceId()).
524 - put(matchingExtraneousGroup.id(), group); 563 + put(matchingExtraneousGroup.id(), group);
525 addOrUpdateGroupEntry(matchingExtraneousGroup); 564 addOrUpdateGroupEntry(matchingExtraneousGroup);
526 removeExtraneousGroupEntry(matchingExtraneousGroup); 565 removeExtraneousGroupEntry(matchingExtraneousGroup);
527 return; 566 return;
...@@ -543,11 +582,11 @@ public class DistributedGroupStore ...@@ -543,11 +582,11 @@ public class DistributedGroupStore
543 new DefaultGroupId(groupDesc.givenGroupId())); 582 new DefaultGroupId(groupDesc.givenGroupId()));
544 if (existing != null) { 583 if (existing != null) {
545 log.warn("Group already exists with the same id: 0x{} in dev:{} " 584 log.warn("Group already exists with the same id: 0x{} in dev:{} "
546 - + "but with different key: {} (request gkey: {})", 585 + + "but with different key: {} (request gkey: {})",
547 - Integer.toHexString(groupDesc.givenGroupId()), 586 + Integer.toHexString(groupDesc.givenGroupId()),
548 - groupDesc.deviceId(), 587 + groupDesc.deviceId(),
549 - existing.appCookie(), 588 + existing.appCookie(),
550 - groupDesc.appCookie()); 589 + groupDesc.appCookie());
551 return; 590 return;
552 } 591 }
553 id = new DefaultGroupId(groupDesc.givenGroupId()); 592 id = new DefaultGroupId(groupDesc.givenGroupId());
...@@ -556,15 +595,15 @@ public class DistributedGroupStore ...@@ -556,15 +595,15 @@ public class DistributedGroupStore
556 StoredGroupEntry group = new DefaultGroup(id, groupDesc); 595 StoredGroupEntry group = new DefaultGroup(id, groupDesc);
557 // Insert the newly created group entry into key and id maps 596 // Insert the newly created group entry into key and id maps
558 getGroupStoreKeyMap(). 597 getGroupStoreKeyMap().
559 - put(new GroupStoreKeyMapKey(groupDesc.deviceId(), 598 + put(new GroupStoreKeyMapKey(groupDesc.deviceId(),
560 - groupDesc.appCookie()), group); 599 + groupDesc.appCookie()), group);
561 // Ensure it also inserted into group id based table to 600 // Ensure it also inserted into group id based table to
562 // avoid any chances of duplication in group id generation 601 // avoid any chances of duplication in group id generation
563 getGroupIdTable(groupDesc.deviceId()). 602 getGroupIdTable(groupDesc.deviceId()).
564 - put(id, group); 603 + put(id, group);
565 log.debug("storeGroupDescriptionInternal: Processing Group ADD request for Id {} in device {}", 604 log.debug("storeGroupDescriptionInternal: Processing Group ADD request for Id {} in device {}",
566 - id, 605 + id,
567 - groupDesc.deviceId()); 606 + groupDesc.deviceId());
568 notifyDelegate(new GroupEvent(GroupEvent.Type.GROUP_ADD_REQUESTED, 607 notifyDelegate(new GroupEvent(GroupEvent.Type.GROUP_ADD_REQUESTED,
569 group)); 608 group));
570 } 609 }
...@@ -573,10 +612,10 @@ public class DistributedGroupStore ...@@ -573,10 +612,10 @@ public class DistributedGroupStore
573 * Updates the existing group entry with the information 612 * Updates the existing group entry with the information
574 * from group description. 613 * from group description.
575 * 614 *
576 - * @param deviceId the device ID 615 + * @param deviceId the device ID
577 * @param oldAppCookie the current group key 616 * @param oldAppCookie the current group key
578 - * @param type update type 617 + * @param type update type
579 - * @param newBuckets group buckets for updates 618 + * @param newBuckets group buckets for updates
580 * @param newAppCookie optional new group key 619 * @param newAppCookie optional new group key
581 */ 620 */
582 @Override 621 @Override
...@@ -592,8 +631,8 @@ public class DistributedGroupStore ...@@ -592,8 +631,8 @@ public class DistributedGroupStore
592 deviceId); 631 deviceId);
593 if (mastershipService.getMasterFor(deviceId) == null) { 632 if (mastershipService.getMasterFor(deviceId) == null) {
594 log.error("No Master for device {}..." 633 log.error("No Master for device {}..."
595 - + "Can not perform update group operation", 634 + + "Can not perform update group operation",
596 - deviceId); 635 + deviceId);
597 //TODO: Send Group operation failure event 636 //TODO: Send Group operation failure event
598 return; 637 return;
599 } 638 }
...@@ -605,16 +644,16 @@ public class DistributedGroupStore ...@@ -605,16 +644,16 @@ public class DistributedGroupStore
605 newAppCookie); 644 newAppCookie);
606 645
607 clusterCommunicator.unicast(groupOp, 646 clusterCommunicator.unicast(groupOp,
608 - GroupStoreMessageSubjects.REMOTE_GROUP_OP_REQUEST, 647 + GroupStoreMessageSubjects.REMOTE_GROUP_OP_REQUEST,
609 - clusterMsgSerializer::serialize, 648 + clusterMsgSerializer::serialize,
610 - mastershipService.getMasterFor(deviceId)).whenComplete((result, error) -> { 649 + mastershipService.getMasterFor(deviceId)).whenComplete((result, error) -> {
611 - if (error != null) { 650 + if (error != null) {
612 - log.warn("Failed to send request to master: {} to {}", 651 + log.warn("Failed to send request to master: {} to {}",
613 - groupOp, 652 + groupOp,
614 - mastershipService.getMasterFor(deviceId), error); 653 + mastershipService.getMasterFor(deviceId), error);
615 - } 654 + }
616 - //TODO: Send Group operation failure event 655 + //TODO: Send Group operation failure event
617 - }); 656 + });
618 return; 657 return;
619 } 658 }
620 log.debug("updateGroupDescription for device {} is getting handled locally", 659 log.debug("updateGroupDescription for device {} is getting handled locally",
...@@ -627,15 +666,15 @@ public class DistributedGroupStore ...@@ -627,15 +666,15 @@ public class DistributedGroupStore
627 } 666 }
628 667
629 private void updateGroupDescriptionInternal(DeviceId deviceId, 668 private void updateGroupDescriptionInternal(DeviceId deviceId,
630 - GroupKey oldAppCookie, 669 + GroupKey oldAppCookie,
631 - UpdateType type, 670 + UpdateType type,
632 - GroupBuckets newBuckets, 671 + GroupBuckets newBuckets,
633 - GroupKey newAppCookie) { 672 + GroupKey newAppCookie) {
634 // Check if a group is existing with the provided key 673 // Check if a group is existing with the provided key
635 Group oldGroup = getGroup(deviceId, oldAppCookie); 674 Group oldGroup = getGroup(deviceId, oldAppCookie);
636 if (oldGroup == null) { 675 if (oldGroup == null) {
637 log.warn("updateGroupDescriptionInternal: Group not found...strange. " 676 log.warn("updateGroupDescriptionInternal: Group not found...strange. "
638 - + "GroupKey:{} DeviceId:{}", oldAppCookie, deviceId); 677 + + "GroupKey:{} DeviceId:{}", oldAppCookie, deviceId);
639 return; 678 return;
640 } 679 }
641 680
...@@ -656,9 +695,9 @@ public class DistributedGroupStore ...@@ -656,9 +695,9 @@ public class DistributedGroupStore
656 StoredGroupEntry newGroup = new DefaultGroup(oldGroup.id(), 695 StoredGroupEntry newGroup = new DefaultGroup(oldGroup.id(),
657 updatedGroupDesc); 696 updatedGroupDesc);
658 log.debug("updateGroupDescriptionInternal: group entry {} in device {} moving from {} to PENDING_UPDATE", 697 log.debug("updateGroupDescriptionInternal: group entry {} in device {} moving from {} to PENDING_UPDATE",
659 - oldGroup.id(), 698 + oldGroup.id(),
660 - oldGroup.deviceId(), 699 + oldGroup.deviceId(),
661 - oldGroup.state()); 700 + oldGroup.state());
662 newGroup.setState(GroupState.PENDING_UPDATE); 701 newGroup.setState(GroupState.PENDING_UPDATE);
663 newGroup.setLife(oldGroup.life()); 702 newGroup.setLife(oldGroup.life());
664 newGroup.setPackets(oldGroup.packets()); 703 newGroup.setPackets(oldGroup.packets());
...@@ -669,12 +708,12 @@ public class DistributedGroupStore ...@@ -669,12 +708,12 @@ public class DistributedGroupStore
669 log.debug("updateGroupDescriptionInternal with type {}: Group updated with buckets", 708 log.debug("updateGroupDescriptionInternal with type {}: Group updated with buckets",
670 type); 709 type);
671 getGroupStoreKeyMap(). 710 getGroupStoreKeyMap().
672 - put(new GroupStoreKeyMapKey(newGroup.deviceId(), 711 + put(new GroupStoreKeyMapKey(newGroup.deviceId(),
673 - newGroup.appCookie()), newGroup); 712 + newGroup.appCookie()), newGroup);
674 notifyDelegate(new GroupEvent(Type.GROUP_UPDATE_REQUESTED, newGroup)); 713 notifyDelegate(new GroupEvent(Type.GROUP_UPDATE_REQUESTED, newGroup));
675 } else { 714 } else {
676 log.warn("updateGroupDescriptionInternal with type {}: No " 715 log.warn("updateGroupDescriptionInternal with type {}: No "
677 - + "change in the buckets in update", type); 716 + + "change in the buckets in update", type);
678 } 717 }
679 } 718 }
680 719
...@@ -688,7 +727,7 @@ public class DistributedGroupStore ...@@ -688,7 +727,7 @@ public class DistributedGroupStore
688 if (type == UpdateType.ADD) { 727 if (type == UpdateType.ADD) {
689 // Check if the any of the new buckets are part of 728 // Check if the any of the new buckets are part of
690 // the old bucket list 729 // the old bucket list
691 - for (GroupBucket addBucket:buckets.buckets()) { 730 + for (GroupBucket addBucket : buckets.buckets()) {
692 if (!newBucketList.contains(addBucket)) { 731 if (!newBucketList.contains(addBucket)) {
693 newBucketList.add(addBucket); 732 newBucketList.add(addBucket);
694 groupDescUpdated = true; 733 groupDescUpdated = true;
...@@ -697,7 +736,7 @@ public class DistributedGroupStore ...@@ -697,7 +736,7 @@ public class DistributedGroupStore
697 } else if (type == UpdateType.REMOVE) { 736 } else if (type == UpdateType.REMOVE) {
698 // Check if the to be removed buckets are part of the 737 // Check if the to be removed buckets are part of the
699 // old bucket list 738 // old bucket list
700 - for (GroupBucket removeBucket:buckets.buckets()) { 739 + for (GroupBucket removeBucket : buckets.buckets()) {
701 if (newBucketList.contains(removeBucket)) { 740 if (newBucketList.contains(removeBucket)) {
702 newBucketList.remove(removeBucket); 741 newBucketList.remove(removeBucket);
703 groupDescUpdated = true; 742 groupDescUpdated = true;
...@@ -715,7 +754,7 @@ public class DistributedGroupStore ...@@ -715,7 +754,7 @@ public class DistributedGroupStore
715 /** 754 /**
716 * Triggers deleting the existing group entry. 755 * Triggers deleting the existing group entry.
717 * 756 *
718 - * @param deviceId the device ID 757 + * @param deviceId the device ID
719 * @param appCookie the group key 758 * @param appCookie the group key
720 */ 759 */
721 @Override 760 @Override
...@@ -728,8 +767,8 @@ public class DistributedGroupStore ...@@ -728,8 +767,8 @@ public class DistributedGroupStore
728 deviceId); 767 deviceId);
729 if (mastershipService.getMasterFor(deviceId) == null) { 768 if (mastershipService.getMasterFor(deviceId) == null) {
730 log.error("No Master for device {}..." 769 log.error("No Master for device {}..."
731 - + "Can not perform delete group operation", 770 + + "Can not perform delete group operation",
732 - deviceId); 771 + deviceId);
733 //TODO: Send Group operation failure event 772 //TODO: Send Group operation failure event
734 return; 773 return;
735 } 774 }
...@@ -738,16 +777,16 @@ public class DistributedGroupStore ...@@ -738,16 +777,16 @@ public class DistributedGroupStore
738 appCookie); 777 appCookie);
739 778
740 clusterCommunicator.unicast(groupOp, 779 clusterCommunicator.unicast(groupOp,
741 - GroupStoreMessageSubjects.REMOTE_GROUP_OP_REQUEST, 780 + GroupStoreMessageSubjects.REMOTE_GROUP_OP_REQUEST,
742 - clusterMsgSerializer::serialize, 781 + clusterMsgSerializer::serialize,
743 - mastershipService.getMasterFor(deviceId)).whenComplete((result, error) -> { 782 + mastershipService.getMasterFor(deviceId)).whenComplete((result, error) -> {
744 - if (error != null) { 783 + if (error != null) {
745 - log.warn("Failed to send request to master: {} to {}", 784 + log.warn("Failed to send request to master: {} to {}",
746 - groupOp, 785 + groupOp,
747 - mastershipService.getMasterFor(deviceId), error); 786 + mastershipService.getMasterFor(deviceId), error);
748 - } 787 + }
749 - //TODO: Send Group operation failure event 788 + //TODO: Send Group operation failure event
750 - }); 789 + });
751 return; 790 return;
752 } 791 }
753 log.debug("deleteGroupDescription in device {} is getting handled locally", 792 log.debug("deleteGroupDescription in device {} is getting handled locally",
...@@ -764,14 +803,14 @@ public class DistributedGroupStore ...@@ -764,14 +803,14 @@ public class DistributedGroupStore
764 } 803 }
765 804
766 log.debug("deleteGroupDescriptionInternal: group entry {} in device {} moving from {} to PENDING_DELETE", 805 log.debug("deleteGroupDescriptionInternal: group entry {} in device {} moving from {} to PENDING_DELETE",
767 - existing.id(), 806 + existing.id(),
768 - existing.deviceId(), 807 + existing.deviceId(),
769 - existing.state()); 808 + existing.state());
770 synchronized (existing) { 809 synchronized (existing) {
771 existing.setState(GroupState.PENDING_DELETE); 810 existing.setState(GroupState.PENDING_DELETE);
772 getGroupStoreKeyMap(). 811 getGroupStoreKeyMap().
773 - put(new GroupStoreKeyMapKey(existing.deviceId(), existing.appCookie()), 812 + put(new GroupStoreKeyMapKey(existing.deviceId(), existing.appCookie()),
774 - existing); 813 + existing);
775 } 814 }
776 log.debug("deleteGroupDescriptionInternal: in device {} issuing GROUP_REMOVE_REQUESTED", 815 log.debug("deleteGroupDescriptionInternal: in device {} issuing GROUP_REMOVE_REQUESTED",
777 deviceId); 816 deviceId);
...@@ -792,15 +831,15 @@ public class DistributedGroupStore ...@@ -792,15 +831,15 @@ public class DistributedGroupStore
792 831
793 if (existing != null) { 832 if (existing != null) {
794 log.trace("addOrUpdateGroupEntry: updating group entry {} in device {}", 833 log.trace("addOrUpdateGroupEntry: updating group entry {} in device {}",
795 - group.id(), 834 + group.id(),
796 - group.deviceId()); 835 + group.deviceId());
797 synchronized (existing) { 836 synchronized (existing) {
798 - for (GroupBucket bucket:group.buckets().buckets()) { 837 + for (GroupBucket bucket : group.buckets().buckets()) {
799 Optional<GroupBucket> matchingBucket = 838 Optional<GroupBucket> matchingBucket =
800 existing.buckets().buckets() 839 existing.buckets().buckets()
801 - .stream() 840 + .stream()
802 - .filter((existingBucket)->(existingBucket.equals(bucket))) 841 + .filter((existingBucket) -> (existingBucket.equals(bucket)))
803 - .findFirst(); 842 + .findFirst();
804 if (matchingBucket.isPresent()) { 843 if (matchingBucket.isPresent()) {
805 ((StoredGroupBucketEntry) matchingBucket. 844 ((StoredGroupBucketEntry) matchingBucket.
806 get()).setPackets(bucket.packets()); 845 get()).setPackets(bucket.packets());
...@@ -808,38 +847,39 @@ public class DistributedGroupStore ...@@ -808,38 +847,39 @@ public class DistributedGroupStore
808 get()).setBytes(bucket.bytes()); 847 get()).setBytes(bucket.bytes());
809 } else { 848 } else {
810 log.warn("addOrUpdateGroupEntry: No matching " 849 log.warn("addOrUpdateGroupEntry: No matching "
811 - + "buckets to update stats"); 850 + + "buckets to update stats");
812 } 851 }
813 } 852 }
814 existing.setLife(group.life()); 853 existing.setLife(group.life());
815 existing.setPackets(group.packets()); 854 existing.setPackets(group.packets());
816 existing.setBytes(group.bytes()); 855 existing.setBytes(group.bytes());
856 + existing.setReferenceCount(group.referenceCount());
817 if ((existing.state() == GroupState.PENDING_ADD) || 857 if ((existing.state() == GroupState.PENDING_ADD) ||
818 - (existing.state() == GroupState.PENDING_ADD_RETRY)) { 858 + (existing.state() == GroupState.PENDING_ADD_RETRY)) {
819 log.trace("addOrUpdateGroupEntry: group entry {} in device {} moving from {} to ADDED", 859 log.trace("addOrUpdateGroupEntry: group entry {} in device {} moving from {} to ADDED",
820 - existing.id(), 860 + existing.id(),
821 - existing.deviceId(), 861 + existing.deviceId(),
822 - existing.state()); 862 + existing.state());
823 existing.setState(GroupState.ADDED); 863 existing.setState(GroupState.ADDED);
824 existing.setIsGroupStateAddedFirstTime(true); 864 existing.setIsGroupStateAddedFirstTime(true);
825 event = new GroupEvent(Type.GROUP_ADDED, existing); 865 event = new GroupEvent(Type.GROUP_ADDED, existing);
826 } else { 866 } else {
827 log.trace("addOrUpdateGroupEntry: group entry {} in device {} moving from {} to ADDED", 867 log.trace("addOrUpdateGroupEntry: group entry {} in device {} moving from {} to ADDED",
828 - existing.id(), 868 + existing.id(),
829 - existing.deviceId(), 869 + existing.deviceId(),
830 - GroupState.PENDING_UPDATE); 870 + GroupState.PENDING_UPDATE);
831 existing.setState(GroupState.ADDED); 871 existing.setState(GroupState.ADDED);
832 existing.setIsGroupStateAddedFirstTime(false); 872 existing.setIsGroupStateAddedFirstTime(false);
833 event = new GroupEvent(Type.GROUP_UPDATED, existing); 873 event = new GroupEvent(Type.GROUP_UPDATED, existing);
834 } 874 }
835 //Re-PUT map entries to trigger map update events 875 //Re-PUT map entries to trigger map update events
836 getGroupStoreKeyMap(). 876 getGroupStoreKeyMap().
837 - put(new GroupStoreKeyMapKey(existing.deviceId(), 877 + put(new GroupStoreKeyMapKey(existing.deviceId(),
838 - existing.appCookie()), existing); 878 + existing.appCookie()), existing);
839 } 879 }
840 } else { 880 } else {
841 log.warn("addOrUpdateGroupEntry: Group update " 881 log.warn("addOrUpdateGroupEntry: Group update "
842 - + "happening for a non-existing entry in the map"); 882 + + "happening for a non-existing entry in the map");
843 } 883 }
844 884
845 if (event != null) { 885 if (event != null) {
...@@ -859,8 +899,8 @@ public class DistributedGroupStore ...@@ -859,8 +899,8 @@ public class DistributedGroupStore
859 899
860 if (existing != null) { 900 if (existing != null) {
861 log.debug("removeGroupEntry: removing group entry {} in device {}", 901 log.debug("removeGroupEntry: removing group entry {} in device {}",
862 - group.id(), 902 + group.id(),
863 - group.deviceId()); 903 + group.deviceId());
864 //Removal from groupid based map will happen in the 904 //Removal from groupid based map will happen in the
865 //map update listener 905 //map update listener
866 getGroupStoreKeyMap().remove(new GroupStoreKeyMapKey(existing.deviceId(), 906 getGroupStoreKeyMap().remove(new GroupStoreKeyMapKey(existing.deviceId(),
...@@ -868,9 +908,9 @@ public class DistributedGroupStore ...@@ -868,9 +908,9 @@ public class DistributedGroupStore
868 notifyDelegate(new GroupEvent(Type.GROUP_REMOVED, existing)); 908 notifyDelegate(new GroupEvent(Type.GROUP_REMOVED, existing));
869 } else { 909 } else {
870 log.warn("removeGroupEntry for {} in device{} is " 910 log.warn("removeGroupEntry for {} in device{} is "
871 - + "not existing in our maps", 911 + + "not existing in our maps",
872 - group.id(), 912 + group.id(),
873 - group.deviceId()); 913 + group.deviceId());
874 } 914 }
875 } 915 }
876 916
...@@ -900,13 +940,13 @@ public class DistributedGroupStore ...@@ -900,13 +940,13 @@ public class DistributedGroupStore
900 // Execute all pending group requests 940 // Execute all pending group requests
901 List<StoredGroupEntry> pendingGroupRequests = 941 List<StoredGroupEntry> pendingGroupRequests =
902 getPendingGroupKeyTable().values() 942 getPendingGroupKeyTable().values()
903 - .stream() 943 + .stream()
904 - .filter(g-> g.deviceId().equals(deviceId)) 944 + .filter(g -> g.deviceId().equals(deviceId))
905 - .collect(Collectors.toList()); 945 + .collect(Collectors.toList());
906 log.debug("processing pending group add requests for device {} and number of pending requests {}", 946 log.debug("processing pending group add requests for device {} and number of pending requests {}",
907 - deviceId, 947 + deviceId,
908 - pendingGroupRequests.size()); 948 + pendingGroupRequests.size());
909 - for (Group group:pendingGroupRequests) { 949 + for (Group group : pendingGroupRequests) {
910 GroupDescription tmp = new DefaultGroupDescription( 950 GroupDescription tmp = new DefaultGroupDescription(
911 group.deviceId(), 951 group.deviceId(),
912 group.type(), 952 group.type(),
...@@ -916,7 +956,7 @@ public class DistributedGroupStore ...@@ -916,7 +956,7 @@ public class DistributedGroupStore
916 group.appId()); 956 group.appId());
917 storeGroupDescriptionInternal(tmp); 957 storeGroupDescriptionInternal(tmp);
918 getPendingGroupKeyTable(). 958 getPendingGroupKeyTable().
919 - remove(new GroupStoreKeyMapKey(deviceId, group.appCookie())); 959 + remove(new GroupStoreKeyMapKey(deviceId, group.appCookie()));
920 } 960 }
921 } else { 961 } else {
922 Boolean audited = deviceAuditStatus.get(deviceId); 962 Boolean audited = deviceAuditStatus.get(deviceId);
...@@ -948,11 +988,11 @@ public class DistributedGroupStore ...@@ -948,11 +988,11 @@ public class DistributedGroupStore
948 } 988 }
949 989
950 log.warn("groupOperationFailed: group operation {} failed" 990 log.warn("groupOperationFailed: group operation {} failed"
951 - + "for group {} in device {} with code {}", 991 + + "for group {} in device {} with code {}",
952 - operation.opType(), 992 + operation.opType(),
953 - existing.id(), 993 + existing.id(),
954 - existing.deviceId(), 994 + existing.deviceId(),
955 - operation.failureCode()); 995 + operation.failureCode());
956 if (operation.failureCode() == GroupOperation.GroupMsgErrorCode.GROUP_EXISTS) { 996 if (operation.failureCode() == GroupOperation.GroupMsgErrorCode.GROUP_EXISTS) {
957 log.warn("Current extraneous groups in device:{} are: {}", 997 log.warn("Current extraneous groups in device:{} are: {}",
958 deviceId, 998 deviceId,
...@@ -960,14 +1000,14 @@ public class DistributedGroupStore ...@@ -960,14 +1000,14 @@ public class DistributedGroupStore
960 if (operation.buckets().equals(existing.buckets())) { 1000 if (operation.buckets().equals(existing.buckets())) {
961 if (existing.state() == GroupState.PENDING_ADD) { 1001 if (existing.state() == GroupState.PENDING_ADD) {
962 log.info("GROUP_EXISTS: GroupID and Buckets match for group in pending " 1002 log.info("GROUP_EXISTS: GroupID and Buckets match for group in pending "
963 - + "add state - moving to ADDED for group {} in device {}", 1003 + + "add state - moving to ADDED for group {} in device {}",
964 - existing.id(), deviceId); 1004 + existing.id(), deviceId);
965 addOrUpdateGroupEntry(existing); 1005 addOrUpdateGroupEntry(existing);
966 return; 1006 return;
967 } else { 1007 } else {
968 log.warn("GROUP EXISTS: Group ID matched but buckets did not. " 1008 log.warn("GROUP EXISTS: Group ID matched but buckets did not. "
969 - + "Operation: {} Existing: {}", operation.buckets(), 1009 + + "Operation: {} Existing: {}", operation.buckets(),
970 - existing.buckets()); 1010 + existing.buckets());
971 } 1011 }
972 } 1012 }
973 } 1013 }
...@@ -976,9 +1016,9 @@ public class DistributedGroupStore ...@@ -976,9 +1016,9 @@ public class DistributedGroupStore
976 if (existing.state() == GroupState.PENDING_ADD) { 1016 if (existing.state() == GroupState.PENDING_ADD) {
977 notifyDelegate(new GroupEvent(Type.GROUP_ADD_FAILED, existing)); 1017 notifyDelegate(new GroupEvent(Type.GROUP_ADD_FAILED, existing));
978 log.warn("groupOperationFailed: cleaningup " 1018 log.warn("groupOperationFailed: cleaningup "
979 - + "group {} from store in device {}....", 1019 + + "group {} from store in device {}....",
980 - existing.id(), 1020 + existing.id(),
981 - existing.deviceId()); 1021 + existing.deviceId());
982 //Removal from groupid based map will happen in the 1022 //Removal from groupid based map will happen in the
983 //map update listener 1023 //map update listener
984 getGroupStoreKeyMap().remove(new GroupStoreKeyMapKey(existing.deviceId(), 1024 getGroupStoreKeyMap().remove(new GroupStoreKeyMapKey(existing.deviceId(),
...@@ -999,8 +1039,8 @@ public class DistributedGroupStore ...@@ -999,8 +1039,8 @@ public class DistributedGroupStore
999 @Override 1039 @Override
1000 public void addOrUpdateExtraneousGroupEntry(Group group) { 1040 public void addOrUpdateExtraneousGroupEntry(Group group) {
1001 log.debug("add/update extraneous group entry {} in device {}", 1041 log.debug("add/update extraneous group entry {} in device {}",
1002 - group.id(), 1042 + group.id(),
1003 - group.deviceId()); 1043 + group.deviceId());
1004 ConcurrentMap<GroupId, Group> extraneousIdTable = 1044 ConcurrentMap<GroupId, Group> extraneousIdTable =
1005 getExtraneousGroupIdTable(group.deviceId()); 1045 getExtraneousGroupIdTable(group.deviceId());
1006 extraneousIdTable.put(group.id(), group); 1046 extraneousIdTable.put(group.id(), group);
...@@ -1011,8 +1051,8 @@ public class DistributedGroupStore ...@@ -1011,8 +1051,8 @@ public class DistributedGroupStore
1011 @Override 1051 @Override
1012 public void removeExtraneousGroupEntry(Group group) { 1052 public void removeExtraneousGroupEntry(Group group) {
1013 log.debug("remove extraneous group entry {} of device {} from store", 1053 log.debug("remove extraneous group entry {} of device {} from store",
1014 - group.id(), 1054 + group.id(),
1015 - group.deviceId()); 1055 + group.deviceId());
1016 ConcurrentMap<GroupId, Group> extraneousIdTable = 1056 ConcurrentMap<GroupId, Group> extraneousIdTable =
1017 getExtraneousGroupIdTable(group.deviceId()); 1057 getExtraneousGroupIdTable(group.deviceId());
1018 extraneousIdTable.remove(group.id()); 1058 extraneousIdTable.remove(group.id());
...@@ -1038,7 +1078,7 @@ public class DistributedGroupStore ...@@ -1038,7 +1078,7 @@ public class DistributedGroupStore
1038 StoredGroupEntry group = Versioned.valueOrNull(mapEvent.newValue()); 1078 StoredGroupEntry group = Versioned.valueOrNull(mapEvent.newValue());
1039 if ((key == null) && (group == null)) { 1079 if ((key == null) && (group == null)) {
1040 log.error("GroupStoreKeyMapListener: Received " 1080 log.error("GroupStoreKeyMapListener: Received "
1041 - + "event {} with null entry", mapEvent.type()); 1081 + + "event {} with null entry", mapEvent.type());
1042 return; 1082 return;
1043 } else if (group == null) { 1083 } else if (group == null) {
1044 group = getGroupIdTable(key.deviceId()).values() 1084 group = getGroupIdTable(key.deviceId()).values()
...@@ -1047,7 +1087,7 @@ public class DistributedGroupStore ...@@ -1047,7 +1087,7 @@ public class DistributedGroupStore
1047 .findFirst().get(); 1087 .findFirst().get();
1048 if (group == null) { 1088 if (group == null) {
1049 log.error("GroupStoreKeyMapListener: Received " 1089 log.error("GroupStoreKeyMapListener: Received "
1050 - + "event {} with null entry... can not process", mapEvent.type()); 1090 + + "event {} with null entry... can not process", mapEvent.type());
1051 return; 1091 return;
1052 } 1092 }
1053 } 1093 }
...@@ -1063,13 +1103,13 @@ public class DistributedGroupStore ...@@ -1063,13 +1103,13 @@ public class DistributedGroupStore
1063 if (value.isGroupStateAddedFirstTime()) { 1103 if (value.isGroupStateAddedFirstTime()) {
1064 groupEvent = new GroupEvent(Type.GROUP_ADDED, value); 1104 groupEvent = new GroupEvent(Type.GROUP_ADDED, value);
1065 log.trace("Received first time GROUP_ADDED state update for id {} in device {}", 1105 log.trace("Received first time GROUP_ADDED state update for id {} in device {}",
1066 - group.id(), 1106 + group.id(),
1067 - group.deviceId()); 1107 + group.deviceId());
1068 } else { 1108 } else {
1069 groupEvent = new GroupEvent(Type.GROUP_UPDATED, value); 1109 groupEvent = new GroupEvent(Type.GROUP_UPDATED, value);
1070 log.trace("Received following GROUP_ADDED state update for id {} in device {}", 1110 log.trace("Received following GROUP_ADDED state update for id {} in device {}",
1071 - group.id(), 1111 + group.id(),
1072 - group.deviceId()); 1112 + group.deviceId());
1073 } 1113 }
1074 } 1114 }
1075 } else if (mapEvent.type() == MapEvent.Type.REMOVE) { 1115 } else if (mapEvent.type() == MapEvent.Type.REMOVE) {
...@@ -1086,24 +1126,24 @@ public class DistributedGroupStore ...@@ -1086,24 +1126,24 @@ public class DistributedGroupStore
1086 1126
1087 private void process(GroupStoreMessage groupOp) { 1127 private void process(GroupStoreMessage groupOp) {
1088 log.debug("Received remote group operation {} request for device {}", 1128 log.debug("Received remote group operation {} request for device {}",
1089 - groupOp.type(), 1129 + groupOp.type(),
1090 - groupOp.deviceId()); 1130 + groupOp.deviceId());
1091 - if (!mastershipService.isLocalMaster(groupOp.deviceId())) { 1131 + if (!mastershipService.isLocalMaster(groupOp.deviceId())) {
1092 - log.warn("This node is not MASTER for device {}", groupOp.deviceId()); 1132 + log.warn("This node is not MASTER for device {}", groupOp.deviceId());
1093 - return; 1133 + return;
1094 - } 1134 + }
1095 - if (groupOp.type() == GroupStoreMessage.Type.ADD) { 1135 + if (groupOp.type() == GroupStoreMessage.Type.ADD) {
1096 - storeGroupDescriptionInternal(groupOp.groupDesc()); 1136 + storeGroupDescriptionInternal(groupOp.groupDesc());
1097 - } else if (groupOp.type() == GroupStoreMessage.Type.UPDATE) { 1137 + } else if (groupOp.type() == GroupStoreMessage.Type.UPDATE) {
1098 - updateGroupDescriptionInternal(groupOp.deviceId(), 1138 + updateGroupDescriptionInternal(groupOp.deviceId(),
1099 - groupOp.appCookie(), 1139 + groupOp.appCookie(),
1100 - groupOp.updateType(), 1140 + groupOp.updateType(),
1101 - groupOp.updateBuckets(), 1141 + groupOp.updateBuckets(),
1102 - groupOp.newAppCookie()); 1142 + groupOp.newAppCookie());
1103 - } else if (groupOp.type() == GroupStoreMessage.Type.DELETE) { 1143 + } else if (groupOp.type() == GroupStoreMessage.Type.DELETE) {
1104 - deleteGroupDescriptionInternal(groupOp.deviceId(), 1144 + deleteGroupDescriptionInternal(groupOp.deviceId(),
1105 - groupOp.appCookie()); 1145 + groupOp.appCookie());
1106 - } 1146 + }
1107 } 1147 }
1108 1148
1109 /** 1149 /**
...@@ -1144,6 +1184,7 @@ public class DistributedGroupStore ...@@ -1144,6 +1184,7 @@ public class DistributedGroupStore
1144 1184
1145 protected static class GroupStoreKeyMapKey extends GroupStoreMapKey { 1185 protected static class GroupStoreKeyMapKey extends GroupStoreMapKey {
1146 private final GroupKey appCookie; 1186 private final GroupKey appCookie;
1187 +
1147 public GroupStoreKeyMapKey(DeviceId deviceId, 1188 public GroupStoreKeyMapKey(DeviceId deviceId,
1148 GroupKey appCookie) { 1189 GroupKey appCookie) {
1149 super(deviceId); 1190 super(deviceId);
...@@ -1175,6 +1216,7 @@ public class DistributedGroupStore ...@@ -1175,6 +1216,7 @@ public class DistributedGroupStore
1175 1216
1176 protected static class GroupStoreIdMapKey extends GroupStoreMapKey { 1217 protected static class GroupStoreIdMapKey extends GroupStoreMapKey {
1177 private final GroupId groupId; 1218 private final GroupId groupId;
1219 +
1178 public GroupStoreIdMapKey(DeviceId deviceId, 1220 public GroupStoreIdMapKey(DeviceId deviceId,
1179 GroupId groupId) { 1221 GroupId groupId) {
1180 super(deviceId); 1222 super(deviceId);
...@@ -1228,17 +1270,20 @@ public class DistributedGroupStore ...@@ -1228,17 +1270,20 @@ public class DistributedGroupStore
1228 storedGroupEntries.size(), 1270 storedGroupEntries.size(),
1229 deviceId); 1271 deviceId);
1230 for (Iterator<StoredGroupEntry> it1 = storedGroupEntries.iterator(); 1272 for (Iterator<StoredGroupEntry> it1 = storedGroupEntries.iterator();
1231 - it1.hasNext();) { 1273 + it1.hasNext();) {
1232 Group group = it1.next(); 1274 Group group = it1.next();
1233 log.trace("Stored Group {} for device {}", group, deviceId); 1275 log.trace("Stored Group {} for device {}", group, deviceId);
1234 } 1276 }
1235 1277
1278 + garbageCollect(deviceId, southboundGroupEntries, storedGroupEntries);
1279 +
1236 for (Iterator<Group> it2 = southboundGroupEntries.iterator(); it2.hasNext();) { 1280 for (Iterator<Group> it2 = southboundGroupEntries.iterator(); it2.hasNext();) {
1237 Group group = it2.next(); 1281 Group group = it2.next();
1238 if (storedGroupEntries.remove(group)) { 1282 if (storedGroupEntries.remove(group)) {
1239 // we both have the group, let's update some info then. 1283 // we both have the group, let's update some info then.
1240 log.trace("Group AUDIT: group {} exists in both planes for device {}", 1284 log.trace("Group AUDIT: group {} exists in both planes for device {}",
1241 - group.id(), deviceId); 1285 + group.id(), deviceId);
1286 +
1242 groupAdded(group); 1287 groupAdded(group);
1243 it2.remove(); 1288 it2.remove();
1244 } 1289 }
...@@ -1249,15 +1294,15 @@ public class DistributedGroupStore ...@@ -1249,15 +1294,15 @@ public class DistributedGroupStore
1249 // It is possible that group update is 1294 // It is possible that group update is
1250 // in progress while we got a stale info from switch 1295 // in progress while we got a stale info from switch
1251 if (!storedGroupEntries.remove(getGroup( 1296 if (!storedGroupEntries.remove(getGroup(
1252 - group.deviceId(), group.id()))) { 1297 + group.deviceId(), group.id()))) {
1253 log.warn("Group AUDIT: Inconsistent state:" 1298 log.warn("Group AUDIT: Inconsistent state:"
1254 - + "Group exists in ID based table while " 1299 + + "Group exists in ID based table while "
1255 - + "not present in key based table"); 1300 + + "not present in key based table");
1256 } 1301 }
1257 } else { 1302 } else {
1258 // there are groups in the switch that aren't in the store 1303 // there are groups in the switch that aren't in the store
1259 log.debug("Group AUDIT: extraneous group {} exists in data plane for device {}", 1304 log.debug("Group AUDIT: extraneous group {} exists in data plane for device {}",
1260 - group.id(), deviceId); 1305 + group.id(), deviceId);
1261 extraneousStoredEntries.remove(group); 1306 extraneousStoredEntries.remove(group);
1262 extraneousGroup(group); 1307 extraneousGroup(group);
1263 } 1308 }
...@@ -1265,24 +1310,47 @@ public class DistributedGroupStore ...@@ -1265,24 +1310,47 @@ public class DistributedGroupStore
1265 for (Group group : storedGroupEntries) { 1310 for (Group group : storedGroupEntries) {
1266 // there are groups in the store that aren't in the switch 1311 // there are groups in the store that aren't in the switch
1267 log.debug("Group AUDIT: group {} missing in data plane for device {}", 1312 log.debug("Group AUDIT: group {} missing in data plane for device {}",
1268 - group.id(), deviceId); 1313 + group.id(), deviceId);
1269 groupMissing(group); 1314 groupMissing(group);
1270 } 1315 }
1271 for (Group group : extraneousStoredEntries) { 1316 for (Group group : extraneousStoredEntries) {
1272 // there are groups in the extraneous store that 1317 // there are groups in the extraneous store that
1273 // aren't in the switch 1318 // aren't in the switch
1274 log.debug("Group AUDIT: clearing extraneous group {} from store for device {}", 1319 log.debug("Group AUDIT: clearing extraneous group {} from store for device {}",
1275 - group.id(), deviceId); 1320 + group.id(), deviceId);
1276 removeExtraneousGroupEntry(group); 1321 removeExtraneousGroupEntry(group);
1277 } 1322 }
1278 1323
1279 if (!deviceInitialAuditStatus) { 1324 if (!deviceInitialAuditStatus) {
1280 log.info("Group AUDIT: Setting device {} initial AUDIT completed", 1325 log.info("Group AUDIT: Setting device {} initial AUDIT completed",
1281 - deviceId); 1326 + deviceId);
1282 deviceInitialAuditCompleted(deviceId, true); 1327 deviceInitialAuditCompleted(deviceId, true);
1283 } 1328 }
1284 } 1329 }
1285 1330
1331 + private void garbageCollect(DeviceId deviceId,
1332 + Set<Group> southboundGroupEntries,
1333 + Set<StoredGroupEntry> storedGroupEntries) {
1334 + if (!garbageCollect) {
1335 + return;
1336 + }
1337 +
1338 + Iterator<StoredGroupEntry> it = storedGroupEntries.iterator();
1339 + while (it.hasNext()) {
1340 + StoredGroupEntry group = it.next();
1341 + if (group.state() != GroupState.PENDING_DELETE && checkGroupRefCount(group)) {
1342 + log.debug("Garbage collecting group {} on {}", group, deviceId);
1343 + deleteGroupDescription(deviceId, group.appCookie());
1344 + southboundGroupEntries.remove(group);
1345 + it.remove();
1346 + }
1347 + }
1348 + }
1349 +
1350 + private boolean checkGroupRefCount(Group group) {
1351 + return (group.referenceCount() == 0 && group.age() >= gcThresh);
1352 + }
1353 +
1286 private void groupMissing(Group group) { 1354 private void groupMissing(Group group) {
1287 switch (group.state()) { 1355 switch (group.state()) {
1288 case PENDING_DELETE: 1356 case PENDING_DELETE:
...@@ -1299,14 +1367,14 @@ public class DistributedGroupStore ...@@ -1299,14 +1367,14 @@ public class DistributedGroupStore
1299 StoredGroupEntry existing = 1367 StoredGroupEntry existing =
1300 getStoredGroupEntry(group.deviceId(), group.id()); 1368 getStoredGroupEntry(group.deviceId(), group.id());
1301 log.debug("groupMissing: group entry {} in device {} moving from {} to PENDING_ADD_RETRY", 1369 log.debug("groupMissing: group entry {} in device {} moving from {} to PENDING_ADD_RETRY",
1302 - existing.id(), 1370 + existing.id(),
1303 - existing.deviceId(), 1371 + existing.deviceId(),
1304 - existing.state()); 1372 + existing.state());
1305 existing.setState(Group.GroupState.PENDING_ADD_RETRY); 1373 existing.setState(Group.GroupState.PENDING_ADD_RETRY);
1306 //Re-PUT map entries to trigger map update events 1374 //Re-PUT map entries to trigger map update events
1307 getGroupStoreKeyMap(). 1375 getGroupStoreKeyMap().
1308 - put(new GroupStoreKeyMapKey(existing.deviceId(), 1376 + put(new GroupStoreKeyMapKey(existing.deviceId(),
1309 - existing.appCookie()), existing); 1377 + existing.appCookie()), existing);
1310 notifyDelegate(new GroupEvent(GroupEvent.Type.GROUP_ADD_REQUESTED, 1378 notifyDelegate(new GroupEvent(GroupEvent.Type.GROUP_ADD_REQUESTED,
1311 group)); 1379 group));
1312 break; 1380 break;
......
...@@ -23,6 +23,7 @@ import org.junit.After; ...@@ -23,6 +23,7 @@ import org.junit.After;
23 import org.junit.Before; 23 import org.junit.Before;
24 import org.junit.Test; 24 import org.junit.Test;
25 import org.onlab.junit.TestUtils; 25 import org.onlab.junit.TestUtils;
26 +import org.onosproject.cfg.ComponentConfigAdapter;
26 import org.onosproject.cluster.NodeId; 27 import org.onosproject.cluster.NodeId;
27 import org.onosproject.core.DefaultGroupId; 28 import org.onosproject.core.DefaultGroupId;
28 import org.onosproject.core.GroupId; 29 import org.onosproject.core.GroupId;
...@@ -129,6 +130,7 @@ public class DistributedGroupStoreTest { ...@@ -129,6 +130,7 @@ public class DistributedGroupStoreTest {
129 groupStoreImpl.storageService = new TestStorageService(); 130 groupStoreImpl.storageService = new TestStorageService();
130 groupStoreImpl.clusterCommunicator = new ClusterCommunicationServiceAdapter(); 131 groupStoreImpl.clusterCommunicator = new ClusterCommunicationServiceAdapter();
131 groupStoreImpl.mastershipService = new MasterOfAll(); 132 groupStoreImpl.mastershipService = new MasterOfAll();
133 + groupStoreImpl.cfgService = new ComponentConfigAdapter();
132 groupStoreImpl.activate(); 134 groupStoreImpl.activate();
133 groupStore = groupStoreImpl; 135 groupStore = groupStoreImpl;
134 auditPendingReqQueue = 136 auditPendingReqQueue =
......
...@@ -156,6 +156,11 @@ public class GroupsResourceTest extends ResourceTest { ...@@ -156,6 +156,11 @@ public class GroupsResourceTest extends ResourceTest {
156 } 156 }
157 157
158 @Override 158 @Override
159 + public int age() {
160 + return 0;
161 + }
162 +
163 + @Override
159 public Type type() { 164 public Type type() {
160 return GroupDescription.Type.ALL; 165 return GroupDescription.Type.ALL;
161 } 166 }
......