blob: 47c8f855f227f8987f44d5f3ab0a7ed596f92b31 [file] [log] [blame]
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -08001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2015-present Open Networking Foundation
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -08003 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package org.onosproject.net.group.impl;
17
Carmelo Casconebc7eb852019-04-17 23:10:51 -070018import com.google.common.collect.Iterables;
Jian Lid9b5f552016-03-11 18:15:31 -080019import org.onlab.util.Tools;
Charles Chan0c7c43b2016-01-14 17:39:20 -080020import org.onosproject.cfg.ComponentConfigService;
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -080021import org.onosproject.core.ApplicationId;
Andrea Campanella1ea15102017-09-04 16:00:09 +020022import org.onosproject.mastership.MastershipService;
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -080023import org.onosproject.net.DeviceId;
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -080024import org.onosproject.net.device.DeviceEvent;
25import org.onosproject.net.device.DeviceListener;
26import org.onosproject.net.device.DeviceService;
Jordan Halterman59afc6a2017-10-30 16:12:42 -070027import org.onosproject.net.driver.DriverService;
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -080028import org.onosproject.net.group.Group;
29import org.onosproject.net.group.GroupBuckets;
30import org.onosproject.net.group.GroupDescription;
31import org.onosproject.net.group.GroupEvent;
32import org.onosproject.net.group.GroupKey;
33import org.onosproject.net.group.GroupListener;
34import org.onosproject.net.group.GroupOperation;
35import org.onosproject.net.group.GroupOperations;
36import org.onosproject.net.group.GroupProvider;
37import org.onosproject.net.group.GroupProviderRegistry;
38import org.onosproject.net.group.GroupProviderService;
39import org.onosproject.net.group.GroupService;
40import org.onosproject.net.group.GroupStore;
41import org.onosproject.net.group.GroupStore.UpdateType;
42import org.onosproject.net.group.GroupStoreDelegate;
Jian Lid9b5f552016-03-11 18:15:31 -080043import org.onosproject.net.provider.AbstractListenerProviderRegistry;
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -080044import org.onosproject.net.provider.AbstractProviderService;
Charles Chan0c7c43b2016-01-14 17:39:20 -080045import org.osgi.service.component.ComponentContext;
Ray Milkeyd84f89b2018-08-17 14:54:17 -070046import org.osgi.service.component.annotations.Activate;
47import org.osgi.service.component.annotations.Component;
48import org.osgi.service.component.annotations.Deactivate;
49import org.osgi.service.component.annotations.Modified;
50import org.osgi.service.component.annotations.Reference;
51import org.osgi.service.component.annotations.ReferenceCardinality;
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -080052import org.slf4j.Logger;
53
Thomas Vachuska42e8cce2015-07-29 19:25:18 -070054import java.util.Collection;
55import java.util.Collections;
Charles Chan0c7c43b2016-01-14 17:39:20 -080056import java.util.Dictionary;
Carmelo Casconebc7eb852019-04-17 23:10:51 -070057import java.util.Objects;
Charles Chan07f15f22018-05-08 21:35:50 -070058import java.util.concurrent.ExecutorService;
59import java.util.concurrent.Executors;
Thomas Vachuska42e8cce2015-07-29 19:25:18 -070060
Andrea Campanella1ea15102017-09-04 16:00:09 +020061import static com.google.common.base.Strings.isNullOrEmpty;
62import static org.onlab.util.Tools.get;
Charles Chan07f15f22018-05-08 21:35:50 -070063import static org.onlab.util.Tools.groupedThreads;
Carmelo Casconebc7eb852019-04-17 23:10:51 -070064import static org.onosproject.net.OsgiPropertyConstants.GM_POLL_FREQUENCY;
65import static org.onosproject.net.OsgiPropertyConstants.GM_POLL_FREQUENCY_DEFAULT;
66import static org.onosproject.net.OsgiPropertyConstants.GM_PURGE_ON_DISCONNECTION;
67import static org.onosproject.net.OsgiPropertyConstants.GM_PURGE_ON_DISCONNECTION_DEFAULT;
Changhoon Yoon541ef712015-05-23 17:18:34 +090068import static org.onosproject.security.AppGuard.checkPermission;
Jian Lid9b5f552016-03-11 18:15:31 -080069import static org.onosproject.security.AppPermission.Type.GROUP_READ;
70import static org.onosproject.security.AppPermission.Type.GROUP_WRITE;
Thomas Vachuska42e8cce2015-07-29 19:25:18 -070071import static org.slf4j.LoggerFactory.getLogger;
Changhoon Yoonb856b812015-08-10 03:47:19 +090072
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -080073/**
74 * Provides implementation of the group service APIs.
75 */
Ray Milkeyd04e2272018-10-16 18:20:18 -070076@Component(
77 immediate = true,
78 service = {
79 GroupService.class,
80 GroupProviderRegistry.class
81 },
82 property = {
Ray Milkey2d7bca12018-10-17 14:51:52 -070083 GM_POLL_FREQUENCY + ":Integer=" + GM_POLL_FREQUENCY_DEFAULT,
84 GM_PURGE_ON_DISCONNECTION + ":Boolean=" + GM_PURGE_ON_DISCONNECTION_DEFAULT
Ray Milkeyd04e2272018-10-16 18:20:18 -070085 }
86)
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -080087public class GroupManager
Thomas Vachuska42e8cce2015-07-29 19:25:18 -070088 extends AbstractListenerProviderRegistry<GroupEvent, GroupListener,
89 GroupProvider, GroupProviderService>
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -080090 implements GroupService, GroupProviderRegistry {
91
92 private final Logger log = getLogger(getClass());
93
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -080094 private final GroupStoreDelegate delegate = new InternalGroupStoreDelegate();
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -080095 private final DeviceListener deviceListener = new InternalDeviceListener();
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -080096
Charles Chan07f15f22018-05-08 21:35:50 -070097 private final GroupDriverProvider defaultProvider = new GroupDriverProvider();
98
99 private ExecutorService eventExecutor;
Andrea Campanella1ea15102017-09-04 16:00:09 +0200100
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700101 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -0800102 protected GroupStore store;
103
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700104 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800105 protected DeviceService deviceService;
106
Jordan Halterman59afc6a2017-10-30 16:12:42 -0700107 // Reference the DriverService to ensure the service is bound prior to initialization of the GroupDriverProvider
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700108 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Jordan Halterman59afc6a2017-10-30 16:12:42 -0700109 protected DriverService driverService;
110
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700111 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Charles Chan0c7c43b2016-01-14 17:39:20 -0800112 protected ComponentConfigService cfgService;
113
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700114 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Andrea Campanella1ea15102017-09-04 16:00:09 +0200115 protected MastershipService mastershipService;
116
Thomas Vachuskaf566fa22018-10-30 14:03:36 -0700117 /** Frequency (in seconds) for polling groups via fallback provider. */
Ray Milkeyd04e2272018-10-16 18:20:18 -0700118 private int fallbackGroupPollFrequency = GM_POLL_FREQUENCY_DEFAULT;
Andrea Campanella1ea15102017-09-04 16:00:09 +0200119
Thomas Vachuskaf566fa22018-10-30 14:03:36 -0700120 /** Purge entries associated with a device when the device goes offline. */
Ray Milkeyd04e2272018-10-16 18:20:18 -0700121 private boolean purgeOnDisconnection = GM_PURGE_ON_DISCONNECTION_DEFAULT;
Andrea Campanella1ea15102017-09-04 16:00:09 +0200122
Charles Chan0c7c43b2016-01-14 17:39:20 -0800123
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -0800124 @Activate
Charles Chan0c7c43b2016-01-14 17:39:20 -0800125 public void activate(ComponentContext context) {
Charles Chan07f15f22018-05-08 21:35:50 -0700126 eventExecutor = Executors.newSingleThreadExecutor(groupedThreads("onos/group", "event"));
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -0800127 store.setDelegate(delegate);
128 eventDispatcher.addSink(GroupEvent.class, listenerRegistry);
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800129 deviceService.addListener(deviceListener);
Charles Chan0c7c43b2016-01-14 17:39:20 -0800130 cfgService.registerProperties(getClass());
131 modified(context);
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -0800132 log.info("Started");
133 }
134
135 @Deactivate
136 public void deactivate() {
Charles Chan07f15f22018-05-08 21:35:50 -0700137 eventExecutor.shutdown();
Andrea Campanella5a3c09c2017-12-01 13:57:48 +0100138 defaultProvider.terminate();
Andrea Campanella3f1c61e2016-04-01 17:30:12 -0700139 deviceService.removeListener(deviceListener);
Charles Chan0c7c43b2016-01-14 17:39:20 -0800140 cfgService.unregisterProperties(getClass(), false);
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -0800141 store.unsetDelegate(delegate);
142 eventDispatcher.removeSink(GroupEvent.class);
143 log.info("Stopped");
144 }
145
Charles Chan0c7c43b2016-01-14 17:39:20 -0800146 @Modified
147 public void modified(ComponentContext context) {
148 if (context != null) {
149 readComponentConfiguration(context);
150 }
Andrea Campanella1ea15102017-09-04 16:00:09 +0200151 defaultProvider.init(deviceService, new InternalGroupProviderService(defaultProvider),
152 mastershipService, fallbackGroupPollFrequency);
Andrea Campanella6ee73922016-02-03 18:00:00 -0800153 }
154
155 @Override
156 protected GroupProvider defaultProvider() {
157 return defaultProvider;
Charles Chan0c7c43b2016-01-14 17:39:20 -0800158 }
159
160 /**
161 * Extracts properties from the component configuration context.
162 *
163 * @param context the component context
164 */
165 private void readComponentConfiguration(ComponentContext context) {
166 Dictionary<?, ?> properties = context.getProperties();
167 Boolean flag;
168
Thomas Vachuskaf566fa22018-10-30 14:03:36 -0700169 flag = Tools.isPropertyEnabled(properties, GM_PURGE_ON_DISCONNECTION);
Charles Chan0c7c43b2016-01-14 17:39:20 -0800170 if (flag == null) {
171 log.info("PurgeOnDisconnection is not configured, " +
172 "using current value of {}", purgeOnDisconnection);
173 } else {
174 purgeOnDisconnection = flag;
175 log.info("Configured. PurgeOnDisconnection is {}",
176 purgeOnDisconnection ? "enabled" : "disabled");
177 }
Thomas Vachuskaf566fa22018-10-30 14:03:36 -0700178 String s = get(properties, GM_POLL_FREQUENCY);
Andrea Campanella1ea15102017-09-04 16:00:09 +0200179 try {
Ray Milkeyd04e2272018-10-16 18:20:18 -0700180 fallbackGroupPollFrequency = isNullOrEmpty(s) ? GM_POLL_FREQUENCY_DEFAULT : Integer.parseInt(s);
Andrea Campanella1ea15102017-09-04 16:00:09 +0200181 } catch (NumberFormatException e) {
Ray Milkeyd04e2272018-10-16 18:20:18 -0700182 fallbackGroupPollFrequency = GM_POLL_FREQUENCY_DEFAULT;
Andrea Campanella1ea15102017-09-04 16:00:09 +0200183 }
Charles Chan0c7c43b2016-01-14 17:39:20 -0800184 }
185
186 /**
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -0800187 * Create a group in the specified device with the provided parameters.
188 *
189 * @param groupDesc group creation parameters
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -0800190 */
191 @Override
192 public void addGroup(GroupDescription groupDesc) {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900193 checkPermission(GROUP_WRITE);
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -0800194 store.storeGroupDescription(groupDesc);
195 }
196
197 /**
198 * Return a group object associated to an application cookie.
Thomas Vachuska42e8cce2015-07-29 19:25:18 -0700199 * <p>
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -0800200 * NOTE1: The presence of group object in the system does not
201 * guarantee that the "group" is actually created in device.
202 * GROUP_ADDED notification would confirm the creation of
203 * this group in data plane.
204 *
Thomas Vachuska42e8cce2015-07-29 19:25:18 -0700205 * @param deviceId device identifier
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -0800206 * @param appCookie application cookie to be used for lookup
207 * @return group associated with the application cookie or
Thomas Vachuska42e8cce2015-07-29 19:25:18 -0700208 * NULL if Group is not found for the provided cookie
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -0800209 */
210 @Override
211 public Group getGroup(DeviceId deviceId, GroupKey appCookie) {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900212 checkPermission(GROUP_READ);
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -0800213 return store.getGroup(deviceId, appCookie);
214 }
215
216 /**
217 * Append buckets to existing group. The caller can optionally
218 * associate a new cookie during this updation. GROUP_UPDATED or
219 * GROUP_UPDATE_FAILED notifications would be provided along with
220 * cookie depending on the result of the operation on the device.
221 *
Thomas Vachuska42e8cce2015-07-29 19:25:18 -0700222 * @param deviceId device identifier
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -0800223 * @param oldCookie cookie to be used to retrieve the existing group
Thomas Vachuska42e8cce2015-07-29 19:25:18 -0700224 * @param buckets immutable list of group bucket to be added
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -0800225 * @param newCookie immutable cookie to be used post update operation
Thomas Vachuska42e8cce2015-07-29 19:25:18 -0700226 * @param appId Application Id
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -0800227 */
228 @Override
229 public void addBucketsToGroup(DeviceId deviceId,
Thomas Vachuska42e8cce2015-07-29 19:25:18 -0700230 GroupKey oldCookie,
231 GroupBuckets buckets,
232 GroupKey newCookie,
233 ApplicationId appId) {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900234 checkPermission(GROUP_WRITE);
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -0800235 store.updateGroupDescription(deviceId,
236 oldCookie,
237 UpdateType.ADD,
238 buckets,
239 newCookie);
240 }
241
242 /**
243 * Remove buckets from existing group. The caller can optionally
244 * associate a new cookie during this updation. GROUP_UPDATED or
245 * GROUP_UPDATE_FAILED notifications would be provided along with
246 * cookie depending on the result of the operation on the device.
247 *
Thomas Vachuska42e8cce2015-07-29 19:25:18 -0700248 * @param deviceId device identifier
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -0800249 * @param oldCookie cookie to be used to retrieve the existing group
Thomas Vachuska42e8cce2015-07-29 19:25:18 -0700250 * @param buckets immutable list of group bucket to be removed
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -0800251 * @param newCookie immutable cookie to be used post update operation
Thomas Vachuska42e8cce2015-07-29 19:25:18 -0700252 * @param appId Application Id
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -0800253 */
254 @Override
255 public void removeBucketsFromGroup(DeviceId deviceId,
Thomas Vachuska42e8cce2015-07-29 19:25:18 -0700256 GroupKey oldCookie,
257 GroupBuckets buckets,
258 GroupKey newCookie,
259 ApplicationId appId) {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900260 checkPermission(GROUP_WRITE);
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -0800261 store.updateGroupDescription(deviceId,
262 oldCookie,
263 UpdateType.REMOVE,
264 buckets,
265 newCookie);
266 }
267
Victor Silva0282ab82016-11-15 16:30:27 -0300268 /**
269 * Set buckets for an existing group. The caller can optionally
270 * associate a new cookie during this updation. GROUP_UPDATED or
271 * GROUP_UPDATE_FAILED notifications would be provided along with
272 * cookie depending on the result of the operation on the device.
273 *
274 * This operation overwrites the previous group buckets entirely.
275 *
276 * @param deviceId device identifier
277 * @param oldCookie cookie to be used to retrieve the existing group
278 * @param buckets immutable list of group buckets to be set
279 * @param newCookie immutable cookie to be used post update operation
280 * @param appId Application Id
281 */
282 @Override
283 public void setBucketsForGroup(DeviceId deviceId,
284 GroupKey oldCookie,
285 GroupBuckets buckets,
286 GroupKey newCookie,
287 ApplicationId appId) {
288 checkPermission(GROUP_WRITE);
289 store.updateGroupDescription(deviceId,
290 oldCookie,
291 UpdateType.SET,
292 buckets,
293 newCookie);
294 }
295
Kavitha Alagesanc69c66a2016-06-15 14:26:04 +0530296 @Override
297 public void purgeGroupEntries(DeviceId deviceId) {
298 checkPermission(GROUP_WRITE);
299 store.purgeGroupEntry(deviceId);
300 }
301
Victor Silva4e8b7832016-08-17 17:11:19 -0300302 @Override
303 public void purgeGroupEntries() {
304 checkPermission(GROUP_WRITE);
305 store.purgeGroupEntries();
306 }
Kavitha Alagesanc69c66a2016-06-15 14:26:04 +0530307
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -0800308 /**
309 * Delete a group associated to an application cookie.
310 * GROUP_DELETED or GROUP_DELETE_FAILED notifications would be
311 * provided along with cookie depending on the result of the
312 * operation on the device.
313 *
Thomas Vachuska42e8cce2015-07-29 19:25:18 -0700314 * @param deviceId device identifier
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -0800315 * @param appCookie application cookie to be used for lookup
Thomas Vachuska42e8cce2015-07-29 19:25:18 -0700316 * @param appId Application Id
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -0800317 */
318 @Override
319 public void removeGroup(DeviceId deviceId,
320 GroupKey appCookie,
321 ApplicationId appId) {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900322 checkPermission(GROUP_WRITE);
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -0800323 store.deleteGroupDescription(deviceId, appCookie);
324 }
325
326 /**
327 * Retrieve all groups created by an application in the specified device
328 * as seen by current controller instance.
329 *
330 * @param deviceId device identifier
Thomas Vachuska42e8cce2015-07-29 19:25:18 -0700331 * @param appId application id
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -0800332 * @return collection of immutable group objects created by the application
333 */
334 @Override
335 public Iterable<Group> getGroups(DeviceId deviceId,
336 ApplicationId appId) {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900337 checkPermission(GROUP_READ);
Carmelo Casconebc7eb852019-04-17 23:10:51 -0700338 return Iterables.filter(
339 store.getGroups(deviceId),
340 g -> g != null && Objects.equals(g.appId(), appId));
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -0800341 }
342
Jonathan Hart32600692015-03-09 10:38:40 -0700343 @Override
344 public Iterable<Group> getGroups(DeviceId deviceId) {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900345 checkPermission(GROUP_READ);
Jonathan Hart32600692015-03-09 10:38:40 -0700346 return store.getGroups(deviceId);
347 }
348
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -0800349 @Override
350 protected GroupProviderService createProviderService(GroupProvider provider) {
351 return new InternalGroupProviderService(provider);
352 }
353
354 private class InternalGroupStoreDelegate implements GroupStoreDelegate {
355 @Override
356 public void notify(GroupEvent event) {
357 final Group group = event.subject();
358 GroupProvider groupProvider =
359 getProvider(group.deviceId());
360 GroupOperations groupOps = null;
361 switch (event.type()) {
Thomas Vachuska42e8cce2015-07-29 19:25:18 -0700362 case GROUP_ADD_REQUESTED:
363 log.debug("GROUP_ADD_REQUESTED for Group {} on device {}",
364 group.id(), group.deviceId());
365 GroupOperation groupAddOp = GroupOperation.
366 createAddGroupOperation(group.id(),
367 group.type(),
368 group.buckets());
369 groupOps = new GroupOperations(
370 Collections.singletonList(groupAddOp));
371 groupProvider.performGroupOperation(group.deviceId(), groupOps);
372 break;
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -0800373
Thomas Vachuska42e8cce2015-07-29 19:25:18 -0700374 case GROUP_UPDATE_REQUESTED:
375 log.debug("GROUP_UPDATE_REQUESTED for Group {} on device {}",
376 group.id(), group.deviceId());
377 GroupOperation groupModifyOp = GroupOperation.
378 createModifyGroupOperation(group.id(),
379 group.type(),
380 group.buckets());
381 groupOps = new GroupOperations(
382 Collections.singletonList(groupModifyOp));
383 groupProvider.performGroupOperation(group.deviceId(), groupOps);
384 break;
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -0800385
Thomas Vachuska42e8cce2015-07-29 19:25:18 -0700386 case GROUP_REMOVE_REQUESTED:
387 log.debug("GROUP_REMOVE_REQUESTED for Group {} on device {}",
388 group.id(), group.deviceId());
389 GroupOperation groupDeleteOp = GroupOperation.
390 createDeleteGroupOperation(group.id(),
391 group.type());
392 groupOps = new GroupOperations(
393 Collections.singletonList(groupDeleteOp));
394 groupProvider.performGroupOperation(group.deviceId(), groupOps);
395 break;
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -0800396
Thomas Vachuska42e8cce2015-07-29 19:25:18 -0700397 case GROUP_ADDED:
398 case GROUP_UPDATED:
399 case GROUP_REMOVED:
400 case GROUP_ADD_FAILED:
401 case GROUP_UPDATE_FAILED:
402 case GROUP_REMOVE_FAILED:
helenyrwu89470f12016-08-12 13:18:10 -0700403 case GROUP_BUCKET_FAILOVER:
Thomas Vachuska42e8cce2015-07-29 19:25:18 -0700404 post(event);
405 break;
Thomas Vachuska42e8cce2015-07-29 19:25:18 -0700406 default:
407 break;
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -0800408 }
409 }
410 }
411
412 private class InternalGroupProviderService
413 extends AbstractProviderService<GroupProvider>
414 implements GroupProviderService {
415
416 protected InternalGroupProviderService(GroupProvider provider) {
417 super(provider);
418 }
419
420 @Override
Thomas Vachuska42e8cce2015-07-29 19:25:18 -0700421 public void groupOperationFailed(DeviceId deviceId, GroupOperation operation) {
sangho7ff01812015-02-09 16:21:53 -0800422 store.groupOperationFailed(deviceId, operation);
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -0800423 }
424
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -0800425 @Override
426 public void pushGroupMetrics(DeviceId deviceId,
427 Collection<Group> groupEntries) {
Thomas Vachuska42e8cce2015-07-29 19:25:18 -0700428 log.trace("Received group metrics from device {}", deviceId);
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700429 checkValidity();
430 store.pushGroupMetrics(deviceId, groupEntries);
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800431 }
helenyrwu89470f12016-08-12 13:18:10 -0700432
433 @Override
434 public void notifyOfFailovers(Collection<Group> failoverGroups) {
435 store.notifyOfFailovers(failoverGroups);
436 }
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800437 }
438
439 private class InternalDeviceListener implements DeviceListener {
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800440 @Override
441 public void event(DeviceEvent event) {
Charles Chan07f15f22018-05-08 21:35:50 -0700442 eventExecutor.execute(() -> processEventInternal(event));
443 }
444
445 private void processEventInternal(DeviceEvent event) {
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800446 switch (event.type()) {
Thomas Vachuska42e8cce2015-07-29 19:25:18 -0700447 case DEVICE_REMOVED:
448 case DEVICE_AVAILABILITY_CHANGED:
Charles Chan0c7c43b2016-01-14 17:39:20 -0800449 DeviceId deviceId = event.subject().id();
450 if (!deviceService.isAvailable(deviceId)) {
Tian Jian9cb2e9e2018-10-23 16:32:51 +0800451 log.debug("Device {} became unavailable for {}; clearing initial audit status",
452 deviceId, event.type());
453 store.deviceInitialAuditCompleted(deviceId, false);
Charles Chan0c7c43b2016-01-14 17:39:20 -0800454
455 if (purgeOnDisconnection) {
456 store.purgeGroupEntry(deviceId);
457 }
Thomas Vachuska42e8cce2015-07-29 19:25:18 -0700458 }
459 break;
Thomas Vachuska42e8cce2015-07-29 19:25:18 -0700460 default:
461 break;
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -0800462 }
463 }
464 }
helenyrwu89470f12016-08-12 13:18:10 -0700465
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -0800466}