CORD-61 Dynamic XConnect support
- Add new XConnectConfig with unit test
- Gather XConnect features into XConnectHandler
- Introduce ObjectiveError.Type.GROUPREMOVALFAILED
- Rename
- NetworkConfigEventHandler -> AppConfigHandler
- XConnectNextObjectiveStoreKey -> XConnectStoreKey
- Test json file
- Refactor
Change-Id: I8ca3176ed976c71ce9e28b7f3722ce80d49c816f
diff --git a/drivers/default/src/main/java/org/onosproject/driver/pipeline/Ofdpa2GroupHandler.java b/drivers/default/src/main/java/org/onosproject/driver/pipeline/Ofdpa2GroupHandler.java
index 6a2eb7e..80d8332 100644
--- a/drivers/default/src/main/java/org/onosproject/driver/pipeline/Ofdpa2GroupHandler.java
+++ b/drivers/default/src/main/java/org/onosproject/driver/pipeline/Ofdpa2GroupHandler.java
@@ -114,7 +114,8 @@
protected DeviceId deviceId;
private FlowObjectiveStore flowObjectiveStore;
- private Cache<GroupKey, List<OfdpaNextGroup>> pendingNextObjectives;
+ private Cache<GroupKey, List<OfdpaNextGroup>> pendingAddNextObjectives;
+ private Cache<NextObjective, List<GroupKey>> pendingRemoveNextObjectives;
private ConcurrentHashMap<GroupKey, Set<GroupChainElem>> pendingGroups;
private ScheduledExecutorService groupChecker =
Executors.newScheduledThreadPool(2, groupedThreads("onos/pipeliner", "ofdpa2-%d", log));
@@ -134,7 +135,7 @@
this.storageService = serviceDirectory.get(StorageService.class);
this.nextIndex = storageService.getAtomicCounter("group-id-index-counter");
- pendingNextObjectives = CacheBuilder.newBuilder()
+ pendingAddNextObjectives = CacheBuilder.newBuilder()
.expireAfterWrite(20, TimeUnit.SECONDS)
.removalListener((
RemovalNotification<GroupKey, List<OfdpaNextGroup>> notification) -> {
@@ -142,7 +143,16 @@
notification.getValue().forEach(ofdpaNextGrp ->
Ofdpa2Pipeline.fail(ofdpaNextGrp.nextObj,
ObjectiveError.GROUPINSTALLATIONFAILED));
+ }
+ }).build();
+ pendingRemoveNextObjectives = CacheBuilder.newBuilder()
+ .expireAfterWrite(20, TimeUnit.SECONDS)
+ .removalListener((
+ RemovalNotification<NextObjective, List<GroupKey>> notification) -> {
+ if (notification.getCause() == RemovalCause.EXPIRED) {
+ Ofdpa2Pipeline.fail(notification.getKey(),
+ ObjectiveError.GROUPREMOVALFAILED);
}
}).build();
pendingGroups = new ConcurrentHashMap<>();
@@ -1012,6 +1022,11 @@
*/
protected void removeGroup(NextObjective nextObjective, NextGroup next) {
List<Deque<GroupKey>> allgkeys = Ofdpa2Pipeline.appKryo.deserialize(next.data());
+
+ List<GroupKey> groupKeys = allgkeys.stream()
+ .map(Deque::getFirst).collect(Collectors.toList());
+ pendingRemoveNextObjectives.put(nextObjective, groupKeys);
+
allgkeys.forEach(groupChain -> groupChain.forEach(groupKey ->
groupService.removeGroup(deviceId, groupKey, nextObjective.appId())));
flowObjectiveStore.removeNextGroup(nextObjective.id());
@@ -1024,7 +1039,7 @@
private void updatePendingNextObjective(GroupKey key, OfdpaNextGroup value) {
List<OfdpaNextGroup> nextList = new CopyOnWriteArrayList<OfdpaNextGroup>();
nextList.add(value);
- List<OfdpaNextGroup> ret = pendingNextObjectives.asMap()
+ List<OfdpaNextGroup> ret = pendingAddNextObjectives.asMap()
.putIfAbsent(key, nextList);
if (ret != null) {
ret.add(value);
@@ -1079,13 +1094,13 @@
Set<GroupKey> keys = pendingGroups.keySet().stream()
.filter(key -> groupService.getGroup(deviceId, key) != null)
.collect(Collectors.toSet());
- Set<GroupKey> otherkeys = pendingNextObjectives.asMap().keySet().stream()
+ Set<GroupKey> otherkeys = pendingAddNextObjectives.asMap().keySet().stream()
.filter(otherkey -> groupService.getGroup(deviceId, otherkey) != null)
.collect(Collectors.toSet());
keys.addAll(otherkeys);
keys.stream().forEach(key ->
- processPendingGroupsOrNextObjectives(key, false));
+ processPendingAddGroupsOrNextObjs(key, false));
}
}
@@ -1093,14 +1108,20 @@
@Override
public void event(GroupEvent event) {
log.trace("received group event of type {}", event.type());
- if (event.type() == GroupEvent.Type.GROUP_ADDED) {
- GroupKey key = event.subject().appCookie();
- processPendingGroupsOrNextObjectives(key, true);
+ switch (event.type()) {
+ case GROUP_ADDED:
+ processPendingAddGroupsOrNextObjs(event.subject().appCookie(), true);
+ break;
+ case GROUP_REMOVED:
+ processPendingRemoveNextObjs(event.subject().appCookie());
+ break;
+ default:
+ break;
}
}
}
- private void processPendingGroupsOrNextObjectives(GroupKey key, boolean added) {
+ private void processPendingAddGroupsOrNextObjs(GroupKey key, boolean added) {
//first check for group chain
Set<GroupChainElem> gceSet = pendingGroups.remove(key);
if (gceSet != null) {
@@ -1114,9 +1135,9 @@
}
} else {
// otherwise chain complete - check for waiting nextObjectives
- List<OfdpaNextGroup> nextGrpList = pendingNextObjectives.getIfPresent(key);
+ List<OfdpaNextGroup> nextGrpList = pendingAddNextObjectives.getIfPresent(key);
if (nextGrpList != null) {
- pendingNextObjectives.invalidate(key);
+ pendingAddNextObjectives.invalidate(key);
nextGrpList.forEach(nextGrp -> {
log.debug("Group service {} group key {} in device:{}. "
+ "Done implementing next objective: {} <<-->> gid:0x{}",
@@ -1137,6 +1158,17 @@
}
}
+ private void processPendingRemoveNextObjs(GroupKey key) {
+ pendingRemoveNextObjectives.asMap().forEach((nextObjective, groupKeys) -> {
+ if (groupKeys.isEmpty()) {
+ pendingRemoveNextObjectives.invalidate(nextObjective);
+ Ofdpa2Pipeline.pass(nextObjective);
+ } else {
+ groupKeys.remove(key);
+ }
+ });
+ }
+
protected int getNextAvailableIndex() {
return (int) nextIndex.incrementAndGet();
}