From: Mufaddal Makati Date: Mon, 7 Nov 2016 21:50:57 +0000 (-0700) Subject: Solved Bug 6302- X-Git-Tag: release/carbon~8 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=commitdiff_plain;h=32bd7606bed0e1b106f443e30ba4ca919e83ab80;p=packetcable.git Solved Bug 6302- Updated Packetcable project to replace DataChangeListener (deprecated) with DataTreeChangeListener Change-Id: Id59cff4b0e09bcff48c131a0541406358b6aa008 Signed-off-by: Mufaddal Makati --- diff --git a/packetcable-policy-server/src/main/java/org/opendaylight/controller/packetcable/provider/AbstractDataChangeListener.java b/packetcable-policy-server/src/main/java/org/opendaylight/controller/packetcable/provider/AbstractDataChangeListener.java deleted file mode 100644 index b099471..0000000 --- a/packetcable-policy-server/src/main/java/org/opendaylight/controller/packetcable/provider/AbstractDataChangeListener.java +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright (c) 2015 CableLabs and others. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v1.0 which accompanies this distribution, - * and is available at http://www.eclipse.org/legal/epl-v10.html - */ - -package org.opendaylight.controller.packetcable.provider; - -import static com.google.common.base.Preconditions.checkNotNull; -import static org.opendaylight.controller.packetcable.provider.DataChangeUtils.collectTypeFromMap; -import static org.opendaylight.controller.packetcable.provider.DataChangeUtils.collectTypeFromSet; -import static org.opendaylight.controller.packetcable.provider.DataChangeUtils.logChange; -import static org.opendaylight.controller.packetcable.provider.DataChangeUtils.relativeComplement; - -import com.google.common.collect.Maps; -import java.util.Map; -import java.util.Set; -import org.opendaylight.controller.md.sal.binding.api.DataChangeListener; -import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent; -import org.opendaylight.yangtools.yang.binding.DataObject; -import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * @author rvail - */ -public abstract class AbstractDataChangeListener implements DataChangeListener { - - protected final Logger logger = LoggerFactory.getLogger(getClass()); - - private final Class tClass; - - public AbstractDataChangeListener(Class tClass) { - this.tClass = checkNotNull(tClass); - } - - @Override - public void onDataChanged(final AsyncDataChangeEvent, DataObject> asyncDataChangeEvent) { - logger.debug("############{}.onDataChanged()", getClass().getSimpleName()); - logChange(logger, asyncDataChangeEvent); - - final Map, DataObject> allCreatedData = asyncDataChangeEvent.getCreatedData(); - final Map, DataObject> allOriginalData = asyncDataChangeEvent.getOriginalData(); - final Map, DataObject> allUpdatedData = asyncDataChangeEvent.getUpdatedData(); - - // UpdatedData also contains all data that was created, remove it to get the set of only updated data - final Map, DataObject> trueUpdatedData = - relativeComplement(allCreatedData, allUpdatedData); - final Map, DataObject> trueOriginalData = - relativeComplement(allCreatedData, allOriginalData); - - if (!allCreatedData.isEmpty()) { - final Map, T> createdTs = collectTypeFromMap(tClass, allCreatedData); - - if (createdTs.isEmpty()) { - // this should not happen since this object only listens for changes in one tree - logger.warn("Expected created {}(s) but none were found: {}", tClass.getSimpleName(), allCreatedData); - } - else { - handleCreatedData(createdTs); - } - } - - if (!trueUpdatedData.isEmpty()) { - final Map, T> updatedTs = collectTypeFromMap(tClass, trueUpdatedData); - if (updatedTs.isEmpty()) { - // this should not happen since this object should only listen for changes in its tree - logger.warn("Expected updated {}(s) but none were found: {}", tClass.getSimpleName(), trueUpdatedData); - } - else { - - final Map, T> originalTs = collectTypeFromMap(tClass, trueOriginalData); - for (InstanceIdentifier iid : updatedTs.keySet()) { - if (!originalTs.containsKey(iid)) { - logger.warn("No original data for updated object {}", iid); - } - } - - handleUpdatedData(updatedTs, originalTs); - } - } - - final Set> allRemovedPaths = asyncDataChangeEvent.getRemovedPaths(); - if (!allRemovedPaths.isEmpty()) { - final Set> removedTPaths = collectTypeFromSet(tClass, allRemovedPaths); - if (removedTPaths.isEmpty()) { - // this should not happen since this object should only listen for changes in its tree - logger.warn("Expected removed {} but none were found: {}", tClass.getSimpleName(), allRemovedPaths); - } - - Map, T> originalTData = Maps.newHashMapWithExpectedSize(removedTPaths.size()); - for (InstanceIdentifier iid : removedTPaths) { - if (allOriginalData.containsKey(iid)) { - - originalTData.put(iid, (T) allOriginalData.get(iid)); - } - } - - handleRemovedData(removedTPaths, originalTData); - } - } - - protected abstract void handleCreatedData(final Map, T> createdData); - - protected abstract void handleUpdatedData(final Map, T> updatedData, - final Map, T> originalData); - - protected abstract void handleRemovedData(final Set> removedPaths, - final Map, T> originalData); - - - -} diff --git a/packetcable-policy-server/src/main/java/org/opendaylight/controller/packetcable/provider/AbstractDataTreeChangeListener.java b/packetcable-policy-server/src/main/java/org/opendaylight/controller/packetcable/provider/AbstractDataTreeChangeListener.java new file mode 100644 index 0000000..8f5a98b --- /dev/null +++ b/packetcable-policy-server/src/main/java/org/opendaylight/controller/packetcable/provider/AbstractDataTreeChangeListener.java @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2015 CableLabs and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.controller.packetcable.provider; + +import static com.google.common.base.Preconditions.checkNotNull; +import static org.opendaylight.controller.packetcable.provider.DataChangeUtils.collectTypeFromMap; +import static org.opendaylight.controller.packetcable.provider.DataChangeUtils.collectTypeFromSet; +import static org.opendaylight.controller.packetcable.provider.DataChangeUtils.logChange; +import static org.opendaylight.controller.packetcable.provider.DataChangeUtils.relativeComplement; + +import com.google.common.collect.Maps; +import java.util.Map; +import java.util.NoSuchElementException; +import java.util.Set; +import java.util.Collection; + +import org.eclipse.jdt.annotation.NonNull; +import org.opendaylight.controller.md.sal.binding.api.DataObjectModification; +import org.opendaylight.controller.md.sal.binding.api.DataTreeChangeListener; +import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent; +import org.opendaylight.controller.md.sal.binding.api.DataTreeModification; +import org.opendaylight.controller.packetcable.provider.validation.DataValidator; +import org.opendaylight.controller.packetcable.provider.validation.ValidationException; +import org.opendaylight.controller.packetcable.provider.validation.Validator; +import org.opendaylight.controller.packetcable.provider.validation.ValidatorProvider; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.annotation.Nonnull; + +/** + * @author rvail + * @author mmakati + */ +public abstract class AbstractDataTreeChangeListener implements DataTreeChangeListener { + + protected final Logger logger = LoggerFactory.getLogger(getClass()); + + private final Class tClass; + + private final DataValidator dataValidator; + + public AbstractDataTreeChangeListener(Class tClass,DataValidator dataValidator) { + this.tClass = checkNotNull(tClass); + this.dataValidator = checkNotNull(dataValidator); + } + + private ValidationException validateData(final DataTreeModification change){ + InstanceIdentifier iid = change.getRootPath().getRootIdentifier(); + + try { + // getDataAfter should only remove null if the data was removed, but we don't validate on remove. + dataValidator.validate(iid, change.getRootNode().getDataAfter(), Validator.Extent.NODE_AND_SUBTREE); + } + catch (ValidationException e) { + logger.debug("invalid data: {}", change.getRootNode().getDataAfter(), e); + return e; + } + return null; + } + + @Override + public void onDataTreeChanged(@Nonnull Collection> changes) + { + Map, ValidationException> exceptionMap = Maps.newHashMap(); + for (final DataTreeModification change : changes) { + final DataObjectModification root = change.getRootNode(); + switch (root.getModificationType()) { + case SUBTREE_MODIFIED: + try{ + ValidationException validationException = validateData(change); + if(validationException != null){ + handleInvalidData(change,validationException); + } + else { + handleUpdatedData(change); + } + }catch (NoSuchElementException e) { + logger.error("Unable to find validator for data: {}", change.getRootNode().getDataAfter(), e); + } + break; + case WRITE: + try{ + ValidationException validationException = validateData(change); + if(validationException != null){ + handleInvalidData(change,validationException); + } + else { + // Treat an overwrite as an update + boolean update = change.getRootNode().getDataBefore() != null; + if (update) { + handleUpdatedData(change); + } else { + handleCreatedData(change); + } + } + }catch (NoSuchElementException e) { + logger.error("Unable to find validator for data: {}", change.getRootNode().getDataAfter(), e); + } + break; + case DELETE: + handleRemovedData(change); + break; + default: + break; + } + } + } + protected abstract void handleCreatedData(final DataTreeModification change); + + protected abstract void handleUpdatedData(final DataTreeModification change); + + protected abstract void handleRemovedData(final DataTreeModification change); + + protected abstract void handleInvalidData(final DataTreeModification change, ValidationException validationException); + + +} diff --git a/packetcable-policy-server/src/main/java/org/opendaylight/controller/packetcable/provider/PacketcableProvider.java b/packetcable-policy-server/src/main/java/org/opendaylight/controller/packetcable/provider/PacketcableProvider.java index a1e0c3f..a0f5784 100644 --- a/packetcable-policy-server/src/main/java/org/opendaylight/controller/packetcable/provider/PacketcableProvider.java +++ b/packetcable-policy-server/src/main/java/org/opendaylight/controller/packetcable/provider/PacketcableProvider.java @@ -36,8 +36,10 @@ import java.util.concurrent.Future; import javax.annotation.Nonnull; import javax.annotation.concurrent.ThreadSafe; +import org.opendaylight.controller.md.sal.binding.api.DataTreeChangeListener; +import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier; +import org.opendaylight.controller.md.sal.binding.api.DataTreeModification; import org.opendaylight.controller.md.sal.binding.api.DataBroker; -import org.opendaylight.controller.md.sal.binding.api.DataChangeListener; import org.opendaylight.controller.md.sal.binding.api.WriteTransaction; import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException; @@ -139,11 +141,11 @@ public class PacketcableProvider implements BindingAwareProvider, AutoCloseable, private RoutedRpcRegistration rpcRegistration; // Data change listeners/registrations - private final CcapsDataChangeListener ccapsDataChangeListener = new CcapsDataChangeListener(); - private final QosDataChangeListener qosDataChangeListener = new QosDataChangeListener(); + private final CcapsDataTreeChangeListener ccapsDataTreeChangeListener = new CcapsDataTreeChangeListener(); + private final QosDataTreeChangeListener qosDataTreeChangeListener = new QosDataTreeChangeListener(); - private ListenerRegistration ccapsDataChangeListenerRegistration; - private ListenerRegistration qosDataChangeListenerRegistration; + private ListenerRegistration ccapsDataTreeChangeListenerRegistration; + private ListenerRegistration qosDataTreeChangeListenerRegistration; /** * Constructor @@ -160,14 +162,17 @@ public class PacketcableProvider implements BindingAwareProvider, AutoCloseable, dataBroker = session.getSALService(DataBroker.class); mdsalUtils = new MdsalUtils(dataBroker); + final DataTreeIdentifier ccapsDataTreeIid = + new DataTreeIdentifier<>(LogicalDatastoreType.CONFIGURATION, ccapsIID.child(Ccap.class)); - ccapsDataChangeListenerRegistration = - dataBroker.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION, ccapsIID.child(Ccap.class), - ccapsDataChangeListener, DataBroker.DataChangeScope.SUBTREE); + final DataTreeIdentifier appDataTreeIid = + new DataTreeIdentifier<>(LogicalDatastoreType.CONFIGURATION, + qosIID.child(Apps.class).child(App.class).child(Subscribers.class).child(Subscriber.class).child(Gates.class).child(Gate.class)); - qosDataChangeListenerRegistration = dataBroker.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION, - PacketcableProvider.qosIID.child(Apps.class).child(App.class), qosDataChangeListener, - DataBroker.DataChangeScope.SUBTREE); + ccapsDataTreeChangeListenerRegistration = + dataBroker.registerDataTreeChangeListener(ccapsDataTreeIid, new CcapsDataTreeChangeListener()); + + qosDataTreeChangeListenerRegistration = dataBroker.registerDataTreeChangeListener(appDataTreeIid, new QosDataTreeChangeListener()); rpcRegistration = session.addRoutedRpcImplementation(PacketcableService.class, this); logger.info("onSessionInitiated().rpcRgistration: {}", rpcRegistration); @@ -179,12 +184,12 @@ public class PacketcableProvider implements BindingAwareProvider, AutoCloseable, */ @Override public void close() throws ExecutionException, InterruptedException { - if (ccapsDataChangeListenerRegistration != null) { - ccapsDataChangeListenerRegistration.close(); + if (ccapsDataTreeChangeListenerRegistration != null) { + ccapsDataTreeChangeListenerRegistration.close(); } - if (qosDataChangeListenerRegistration != null) { - qosDataChangeListenerRegistration.close(); + if (qosDataTreeChangeListenerRegistration != null) { + qosDataTreeChangeListenerRegistration.close(); } } @@ -305,68 +310,54 @@ public class PacketcableProvider implements BindingAwareProvider, AutoCloseable, // ValidationException does not need to be thrown again @SuppressWarnings("ThrowableResultOfMethodCallIgnored") - private void saveErrors(@Nonnull Map, ValidationException> errorMap, - @Nonnull Map, T> dataMap) { + private void saveErrors(@Nonnull DataTreeModification change, ValidationException exception) { final WriteTransaction writeTransaction = dataBroker.newWriteOnlyTransaction(); + InstanceIdentifier iid = change.getRootPath().getRootIdentifier(); + //final ValidationException exception = exceptionMap.get(change); + final T badData = change.getRootNode().getDataAfter(); - for (InstanceIdentifier iid : errorMap.keySet()) { - - final ValidationException exception = errorMap.get(iid); - final T badData = dataMap.get(iid); - - if (!badData.getImplementedInterface().isAssignableFrom(iid.getTargetType())) { - // InstanceIdentifier does not have the same type as the DataObject - logger.error("Bad InstanceIdentifier to DataObject mapping, {} : {}", iid, badData); - continue; - } - - if (badData instanceof Ccap) { - final Ccap ccap = (Ccap) badData; - - final Ccap opperationalCcap = - new CcapBuilder().setCcapId(ccap.getCcapId()).setError(exception.getErrorMessages()).build(); - + if (badData instanceof Ccap) { + final Ccap ccap = (Ccap) badData; - // type match between iid and badData is done at start of loop - @SuppressWarnings("unchecked") final InstanceIdentifier ccapIID = (InstanceIdentifier) iid; - writeTransaction.put(LogicalDatastoreType.OPERATIONAL, ccapIID, opperationalCcap); - } else if (badData instanceof Gate) { - final Gate gate = (Gate) badData; + final Ccap opperationalCcap = + new CcapBuilder().setCcapId(ccap.getCcapId()).setError(exception.getErrorMessages()).build(); - final Gate operationalGate = - new GateBuilder().setGateId(gate.getGateId()).setError(exception.getErrorMessages()).build(); + @SuppressWarnings("unchecked") final InstanceIdentifier ccapIID = (InstanceIdentifier) change; + writeTransaction.put(LogicalDatastoreType.OPERATIONAL, ccapIID, opperationalCcap); + } else if (badData instanceof Gate) { + final Gate gate = (Gate) badData; - final Gates operationalGates = - new GatesBuilder().setGate(Collections.singletonList(operationalGate)).build(); + final Gate operationalGate = + new GateBuilder().setGateId(gate.getGateId()).setError(exception.getErrorMessages()).build(); - final SubscriberKey subscriberKey = InstanceIdentifier.keyOf(iid.firstIdentifierOf(Subscriber.class)); - final Subscriber operationalSubscriber = - new SubscriberBuilder().setSubscriberId(subscriberKey.getSubscriberId()) - .setGates(operationalGates) - .build(); + final Gates operationalGates = + new GatesBuilder().setGate(Collections.singletonList(operationalGate)).build(); - final Subscribers operationalSubscribers = - new SubscribersBuilder().setSubscriber(Collections.singletonList(operationalSubscriber)) - .build(); + final SubscriberKey subscriberKey = InstanceIdentifier.keyOf(iid.firstIdentifierOf(Subscriber.class)); + final Subscriber operationalSubscriber = + new SubscriberBuilder().setSubscriberId(subscriberKey.getSubscriberId()) + .setGates(operationalGates) + .build(); - final InstanceIdentifier appIID = iid.firstIdentifierOf(App.class); - final AppKey appKey = InstanceIdentifier.keyOf(appIID); - final App operationalApp = - new AppBuilder().setAppId(appKey.getAppId()).setSubscribers(operationalSubscribers).build(); + final Subscribers operationalSubscribers = + new SubscribersBuilder().setSubscriber(Collections.singletonList(operationalSubscriber)) + .build(); + final InstanceIdentifier appIID = iid.firstIdentifierOf(App.class); + final AppKey appKey = InstanceIdentifier.keyOf(appIID); + final App operationalApp = + new AppBuilder().setAppId(appKey.getAppId()).setSubscribers(operationalSubscribers).build(); - writeTransaction.put(LogicalDatastoreType.OPERATIONAL, appIID, operationalApp); - } else { - // If you get here a developer forgot to add a type above - logger.error("Unexpected type requested for error saving: {}", badData); - throw new IllegalStateException("Unsupported type for error saving"); - } + writeTransaction.put(LogicalDatastoreType.OPERATIONAL, appIID, operationalApp); + } else { + // If you get here a developer forgot to add a type above + logger.error("Unexpected type requested for error saving: {}", badData); + throw new IllegalStateException("Unsupported type for error saving"); } - CheckedFuture future = writeTransaction.submit(); try { @@ -523,322 +514,260 @@ public class PacketcableProvider implements BindingAwareProvider, AutoCloseable, /** * Listener for the packetcable:ccaps tree */ - private class CcapsDataChangeListener extends AbstractDataChangeListener { - - private final DataValidator ccapsDataValidator = new DataValidator(new CcapsValidatorProviderFactory().build()); + private class CcapsDataTreeChangeListener extends AbstractDataTreeChangeListener { private final Set> updateQueue = Sets.newConcurrentHashSet(); - public CcapsDataChangeListener() { - super(Ccap.class); + public CcapsDataTreeChangeListener() { + super(Ccap.class,new DataValidator(new CcapsValidatorProviderFactory().build())); } @Override - protected void handleCreatedData(final Map, Ccap> createdCcaps) { - if (createdCcaps.isEmpty()) { - return; - } + protected void handleCreatedData(final DataTreeModification change) { + final Ccap ccap = change.getRootNode().getDataAfter(); + InstanceIdentifier iid = change.getRootPath().getRootIdentifier(); - final Map, ValidationException> errorMap = - ccapsDataValidator.validateOneType(createdCcaps, Validator.Extent.NODE_AND_SUBTREE); - - // validate all new objects an update operational datastore - if (!errorMap.isEmpty()) { - // bad data write errors to operational datastore - saveErrors(errorMap, createdCcaps); - } - - if (createdCcaps.size() > errorMap.size()) { - final Map, Ccap> goodData = - Maps.newHashMapWithExpectedSize(createdCcaps.size() - errorMap.size()); - for (InstanceIdentifier iid : createdCcaps.keySet()) { - if (!errorMap.containsKey(iid)) { - goodData.put(iid, createdCcaps.get(iid)); - } - } - addNewCcaps(goodData); + // add service + if (pcmmServiceMap.containsKey(ccap.getCcapId())) { + logger.error("Already monitoring CCAP - " + ccap); + return; } - } - - private void addNewCcaps(final Map, Ccap> goodData) { - for (InstanceIdentifier iid : goodData.keySet()) { - final Ccap ccap = goodData.get(iid); - - // add service - if (pcmmServiceMap.containsKey(ccap.getCcapId())) { - logger.error("Already monitoring CCAP - " + ccap); - continue; - } - final PCMMService pcmmService = new PCMMService(IPCMMClient.CLIENT_TYPE, ccap); - // TODO - may want to use the AMID but for the client type but probably not??? + final PCMMService pcmmService = new PCMMService(IPCMMClient.CLIENT_TYPE, ccap); + // TODO - may want to use the AMID but for the client type but probably not??? /* - final PCMMService pcmmService = new PCMMService( - thisCcap.getAmId().getAmType().shortValue(), thisCcap); + final PCMMService pcmmService = new PCMMService( + thisCcap.getAmId().getAmType().shortValue(), thisCcap); */ - ConnectionBuilder connectionBuilder = new ConnectionBuilder(); - String message = pcmmService.addCcap(); - if (message.contains("200 OK")) { - pcmmServiceMap.put(ccap.getCcapId(), pcmmService); - ccapMap.put(ccap.getCcapId(), ccap); - updateCcapMaps(ccap); - logger.info("Created CCAP: {}/{} : {}", iid, ccap, message); - logger.info("Created CCAP: {} : {}", iid, message); - - connectionBuilder.setConnected(true).setError(Collections.emptyList()); - } else { - logger.error("Create CCAP Failed: {} : {}", iid, message); - - connectionBuilder.setConnected(false).setError(Collections.singletonList(message)); - } + ConnectionBuilder connectionBuilder = new ConnectionBuilder(); + String message = pcmmService.addCcap(); + if (message.contains("200 OK")) { + pcmmServiceMap.put(ccap.getCcapId(), pcmmService); + ccapMap.put(ccap.getCcapId(), ccap); + updateCcapMaps(ccap); + logger.info("Created CCAP: {}/{} : {}", iid, ccap, message); + logger.info("Created CCAP: {} : {}", iid, message); + + connectionBuilder.setConnected(true).setError(Collections.emptyList()); + } else { + logger.error("Create CCAP Failed: {} : {}", iid, message); - //register rpc - logger.info("Registering CCAP Routed RPC Path..."); - rpcRegistration.registerPath(CcapContext.class, iid); + connectionBuilder.setConnected(false).setError(Collections.singletonList(message)); + } - Optional optionalCcap = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, iid); + //register rpc + logger.info("Registering CCAP Routed RPC Path..."); + rpcRegistration.registerPath(CcapContext.class, iid); - final CcapBuilder responseCcapBuilder; - if (optionalCcap.isPresent()) { - responseCcapBuilder = new CcapBuilder(optionalCcap.get()); - } else { - responseCcapBuilder = new CcapBuilder(); - responseCcapBuilder.setCcapId(ccap.getCcapId()); - } - - responseCcapBuilder.setConnection(connectionBuilder.build()); + Optional optionalCcap = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, iid); - mdsalUtils.put(LogicalDatastoreType.OPERATIONAL, iid, responseCcapBuilder.build()); + final CcapBuilder responseCcapBuilder; + if (optionalCcap.isPresent()) { + responseCcapBuilder = new CcapBuilder(optionalCcap.get()); + } else { + responseCcapBuilder = new CcapBuilder(); + responseCcapBuilder.setCcapId(ccap.getCcapId()); } + responseCcapBuilder.setConnection(connectionBuilder.build()); + + mdsalUtils.put(LogicalDatastoreType.OPERATIONAL, iid, responseCcapBuilder.build()); } @Override - protected void handleUpdatedData(final Map, Ccap> updatedCcaps, - final Map, Ccap> originalCcaps) { - + protected void handleUpdatedData(final DataTreeModification change) { + //final Ccap ccap = (Ccap) change.getRootNode().getIdentifier(); + InstanceIdentifier iid = change.getRootPath().getRootIdentifier(); // TODO actually support updates - // update operation not allowed -- restore the original config object and complain - for (final Map.Entry, Ccap> entry : updatedCcaps.entrySet()) { - if (!originalCcaps.containsKey(entry.getKey())) { - logger.error("No original data found for supposedly updated data: {}", entry.getValue()); - continue; - } - // If this notification is coming from our modification ignore it. - if (updateQueue.contains(entry.getKey())) { - updateQueue.remove(entry.getKey()); - continue; - } + // If this notification is coming from our modification ignore it. + if (updateQueue.contains(iid)) { + updateQueue.remove(iid); + return; + } - final Ccap originalCcap = originalCcaps.get(entry.getKey()); - //final Ccap updatedCcap = entry.getValue(); + final Ccap originalCcap = change.getRootNode().getDataBefore(); + //final Ccap updatedCcap = entry.getValue(); - //register rpc - logger.info("Registering CCAP Routed RPC Path..."); - rpcRegistration.registerPath(CcapContext.class, entry.getKey()); + //register rpc + logger.info("Registering CCAP Routed RPC Path..."); + rpcRegistration.registerPath(CcapContext.class, iid); - // restore the original data - updateQueue.add(entry.getKey()); - mdsalUtils.put(LogicalDatastoreType.CONFIGURATION, entry.getKey(), originalCcap); - logger.error("CCAP update not permitted {}", entry.getKey()); - } + // restore the original data + updateQueue.add(iid); + mdsalUtils.put(LogicalDatastoreType.CONFIGURATION, iid, originalCcap); + logger.error("CCAP update not permitted {}", iid); } @Override - protected void handleRemovedData(final Set> removedCcapPaths, - final Map, Ccap> originalCcaps) { + protected void handleRemovedData(final DataTreeModification change) { - for (InstanceIdentifier iid : removedCcapPaths) { - final Ccap nukedCcap = originalCcaps.get(iid); - removeCcapFromAllMaps(nukedCcap); + InstanceIdentifier iid = change.getRootPath().getRootIdentifier(); + final Ccap nukedCcap = change.getRootNode().getDataBefore(); + removeCcapFromAllMaps(nukedCcap); - //unregister ccap rpc path - logger.info("Un-Registering CCAP Routed RPC Path..."); - rpcRegistration.unregisterPath(CcapContext.class, iid); + //unregister ccap rpc path + logger.info("Un-Registering CCAP Routed RPC Path..."); + rpcRegistration.unregisterPath(CcapContext.class, iid); - mdsalUtils.delete(LogicalDatastoreType.OPERATIONAL, iid); + mdsalUtils.delete(LogicalDatastoreType.OPERATIONAL, iid); - // clean up ccaps level if it is now empty - executor.execute(new CcapsCleaner(iid)); - } + // clean up ccaps level if it is now empty + executor.execute(new CcapsCleaner(iid)); + } + @Override + protected void handleInvalidData(final DataTreeModification change, ValidationException validationException){ + // bad data write errors to operational datastore + saveErrors(change, validationException); } - } + } - private class QosDataChangeListener extends AbstractDataChangeListener { + private class QosDataTreeChangeListener extends AbstractDataTreeChangeListener { - private final DataValidator qosDataValidator = new DataValidator(new QosValidatorProviderFactory().build()); private final Set> updateQueue = Sets.newConcurrentHashSet(); - public QosDataChangeListener() { - super(Gate.class); + public QosDataTreeChangeListener() { + super(Gate.class,new DataValidator(new QosValidatorProviderFactory().build())); } @Override - protected void handleCreatedData(final Map, Gate> createdData) { - - final Map, ValidationException> errorMap = - qosDataValidator.validateOneType(createdData, Validator.Extent.NODE_AND_SUBTREE); - - // validate all new objects an update operational datastore - if (!errorMap.isEmpty()) { - // bad data write errors to operational datastore - saveErrors(errorMap, createdData); - } - - if (createdData.size() > errorMap.size()) { - final Map, Gate> goodData = - Maps.newHashMapWithExpectedSize(createdData.size() - errorMap.size()); - for (InstanceIdentifier iid : createdData.keySet()) { - if (!errorMap.containsKey(iid)) { - goodData.put(iid, createdData.get(iid)); - } - } - addNewGates(goodData); - } - - } - - private void addNewGates(final Map, Gate> createdGates) { + protected void handleCreatedData(final DataTreeModification change) { - for (InstanceIdentifier gateIID : createdGates.keySet()) { - final Gate newGate = createdGates.get(gateIID); + InstanceIdentifier gateIID = change.getRootPath().getRootIdentifier(); + final Gate newGate = change.getRootNode().getDataAfter(); - final String newGatePathStr = makeGatePathString(gateIID); + final String newGatePathStr = makeGatePathString(gateIID); - // if a new app comes along add RPC registration - final InstanceIdentifier appIID = gateIID.firstIdentifierOf(App.class); - // TBD verify if App ID exists first + // if a new app comes along add RPC registration + final InstanceIdentifier appIID = gateIID.firstIdentifierOf(App.class); + // TBD verify if App ID exists first - //register appID RPC path - logger.info("Registering App Routed RPC Path..."); - rpcRegistration.registerPath(AppContext.class, appIID); - - final InstanceIdentifier subscriberIID = gateIID.firstIdentifierOf(Subscriber.class); - final SubscriberKey subscriberKey = InstanceIdentifier.keyOf(subscriberIID); - final InetAddress subscriberAddr = getInetAddress(subscriberKey.getSubscriberId()); - if (subscriberAddr == null) { - final String msg = String.format("subscriberId must be a valid ipaddress: %s", - subscriberKey.getSubscriberId()); - logger.error(msg); - saveGateError(gateIID, newGatePathStr, msg); - continue; - } + //register appID RPC path + logger.info("Registering App Routed RPC Path..."); + rpcRegistration.registerPath(AppContext.class, appIID); - final Ccap ccap = findCcapForSubscriberId(subscriberAddr); - if (ccap == null) { - final String msg = String.format("Unable to find Ccap for subscriber %s: @ %s", - subscriberKey.getSubscriberId(), newGatePathStr); - logger.error(msg); - saveGateError(gateIID, newGatePathStr, msg); - continue; - } + final InstanceIdentifier subscriberIID = gateIID.firstIdentifierOf(Subscriber.class); + final SubscriberKey subscriberKey = InstanceIdentifier.keyOf(subscriberIID); + final InetAddress subscriberAddr = getInetAddress(subscriberKey.getSubscriberId()); + if (subscriberAddr == null) { + final String msg = String.format("subscriberId must be a valid ipaddress: %s", + subscriberKey.getSubscriberId()); + logger.error(msg); + saveGateError(gateIID, newGatePathStr, msg); + return; + } - final PCMMService pcmmService = pcmmServiceMap.get(ccap.getCcapId()); - if (pcmmService == null) { - final String msg = - String.format("Unable to locate PCMM Service for CCAP: %s ; with subscriber: %s", ccap, - subscriberKey.getSubscriberId()); - logger.error(msg); - saveGateError(gateIID, newGatePathStr, msg); - continue; - } + final Ccap ccap = findCcapForSubscriberId(subscriberAddr); + if (ccap == null) { + final String msg = String.format("Unable to find Ccap for subscriber %s: @ %s", + subscriberKey.getSubscriberId(), newGatePathStr); + logger.error(msg); + saveGateError(gateIID, newGatePathStr, msg); + return; + } - // - // set up gate builder with known fields (and some empty ones) - // - final GateBuilder gateBuilder = new GateBuilder(); - gateBuilder.setGateId(newGate.getGateId()) - .setGatePath(newGatePathStr) - .setCcapId(ccap.getCcapId()) - .setTrafficProfile(newGate.getTrafficProfile()) - .setClassifiers(newGate.getClassifiers()) - .setGateSpec(newGate.getGateSpec()) - .setCopsGateState("") - .setCopsGateTimeInfo("") - .setCopsGateUsageInfo(""); + final PCMMService pcmmService = pcmmServiceMap.get(ccap.getCcapId()); + if (pcmmService == null) { + final String msg = + String.format("Unable to locate PCMM Service for CCAP: %s ; with subscriber: %s", ccap, + subscriberKey.getSubscriberId()); + logger.error(msg); + saveGateError(gateIID, newGatePathStr, msg); + return; + } - // - // Right now only ServiceClassName traffic Profile is supported. This logic needs to - // be updated when the yang traffic-profile is extended to support new types - // Override requested Direction using the Ccap configuration information about SCNs and - // their configured direction. - // - final ServiceClassName scn = newGate.getTrafficProfile().getServiceClassName(); - final ServiceFlowDirection scnDirection = findScnOnCcap(scn, ccap); - if (scnDirection == null) { - final String msg = + // + // set up gate builder with known fields (and some empty ones) + // + final GateBuilder gateBuilder = new GateBuilder(); + gateBuilder.setGateId(newGate.getGateId()) + .setGatePath(newGatePathStr) + .setCcapId(ccap.getCcapId()) + .setTrafficProfile(newGate.getTrafficProfile()) + .setClassifiers(newGate.getClassifiers()) + .setGateSpec(newGate.getGateSpec()) + .setCopsGateState("") + .setCopsGateTimeInfo("") + .setCopsGateUsageInfo(""); + + // + // Right now only ServiceClassName traffic Profile is supported. This logic needs to + // be updated when the yang traffic-profile is extended to support new types + // Override requested Direction using the Ccap configuration information about SCNs and + // their configured direction. + // + final ServiceClassName scn = newGate.getTrafficProfile().getServiceClassName(); + final ServiceFlowDirection scnDirection = findScnOnCcap(scn, ccap); + if (scnDirection == null) { + final String msg = String.format("SCN %s not found on CCAP %s for %s", scn, ccap.getCcapId(), newGatePathStr); - logger.error(msg); - saveGateError(gateIID, newGatePathStr, msg); - continue; - } - - // - // since we may be modifying the contents of the original request GateSpec - // to update flow direction (based on the ccap SCN configuration) we need to - // rebuild the requested gate spec and replace the existing one in the gate builder - // - final GateSpecBuilder gateSpecBuilder = new GateSpecBuilder(); - gateSpecBuilder.setDirection(scnDirection); - gateSpecBuilder.setDscpTosMask(newGate.getGateSpec().getDscpTosMask()); - gateSpecBuilder.setDscpTosOverwrite(newGate.getGateSpec().getDscpTosOverwrite()); - final GateSpec gateSpec = gateSpecBuilder.build(); - gateBuilder.setGateSpec(gateSpec); - - // - // build the gate to be requested - // - gateBuilder.setTimestamp(getNowTimeStamp()); + logger.error(msg); + saveGateError(gateIID, newGatePathStr, msg); + return; + } - final Gate requestGate = gateBuilder.build(); + // + // since we may be modifying the contents of the original request GateSpec + // to update flow direction (based on the ccap SCN configuration) we need to + // rebuild the requested gate spec and replace the existing one in the gate builder + // + final GateSpecBuilder gateSpecBuilder = new GateSpecBuilder(); + gateSpecBuilder.setDirection(scnDirection); + gateSpecBuilder.setDscpTosMask(newGate.getGateSpec().getDscpTosMask()); + gateSpecBuilder.setDscpTosOverwrite(newGate.getGateSpec().getDscpTosOverwrite()); + final GateSpec gateSpec = gateSpecBuilder.build(); + gateBuilder.setGateSpec(gateSpec); + + // + // build the gate to be requested + // + gateBuilder.setTimestamp(getNowTimeStamp()); + + final Gate requestGate = gateBuilder.build(); + + // + // send gate request to Ccap + // + PCMMService.GateSendStatus status = + pcmmService.sendGateSet(newGatePathStr, subscriberAddr, requestGate); + if (status.didSucceed()) { + gateMap.put(newGatePathStr, requestGate); + gateCcapMap.put(newGatePathStr, ccap.getCcapId()); // - // send gate request to Ccap + // inquire as to the status, and implementation info of the requested gate // - PCMMService.GateSendStatus status = - pcmmService.sendGateSet(newGatePathStr, subscriberAddr, requestGate); - if (status.didSucceed()) { - gateMap.put(newGatePathStr, requestGate); - gateCcapMap.put(newGatePathStr, ccap.getCcapId()); + PCMMService.GateSendStatus infoStatus = pcmmService.sendGateInfo(newGatePathStr); + if (infoStatus.didSucceed()) { // - // inquire as to the status, and implementation info of the requested gate + // update builder with info for operational storage // - PCMMService.GateSendStatus infoStatus = pcmmService.sendGateInfo(newGatePathStr); - - if (infoStatus.didSucceed()) { - // - // update builder with info for operational storage - // - gateBuilder.setCopsGateState( - infoStatus.getCopsGateState() + "/" + infoStatus.getCopsGateStateReason()) - .setCopsGateTimeInfo(infoStatus.getCopsGateTimeInfo()) - .setCopsGateUsageInfo(infoStatus.getCopsGateUsageInfo()) - .setCopsGateId(status.getCopsGateId()); - } else { - List errors = new ArrayList<>(2); - - // Keep GateSetErrors - if (gateBuilder.getError() != null) { - errors.addAll(gateBuilder.getError()); - } + gateBuilder.setCopsGateState( + infoStatus.getCopsGateState() + "/" + infoStatus.getCopsGateStateReason()) + .setCopsGateTimeInfo(infoStatus.getCopsGateTimeInfo()) + .setCopsGateUsageInfo(infoStatus.getCopsGateUsageInfo()) + .setCopsGateId(status.getCopsGateId()); + } else { + List errors = new ArrayList<>(2); - errors.add(infoStatus.getMessage()); - gateBuilder.setError(errors); + // Keep GateSetErrors + if (gateBuilder.getError() != null) { + errors.addAll(gateBuilder.getError()); } - } - else { - gateBuilder.setError(Collections.singletonList(status.getMessage())); - } - Gate operationalGate = gateBuilder.build(); - - mdsalUtils.put(LogicalDatastoreType.OPERATIONAL, gateIID, operationalGate); + errors.add(infoStatus.getMessage()); + gateBuilder.setError(errors); + } + } + else { + gateBuilder.setError(Collections.singletonList(status.getMessage())); } + Gate operationalGate = gateBuilder.build(); + mdsalUtils.put(LogicalDatastoreType.OPERATIONAL, gateIID, operationalGate); } private void saveGateError(@Nonnull final InstanceIdentifier gateIID, @Nonnull final String gatePathStr, @@ -860,67 +789,61 @@ public class PacketcableProvider implements BindingAwareProvider, AutoCloseable, } @Override - protected void handleUpdatedData(final Map, Gate> updatedData, - final Map, Gate> originalData) { + protected void handleUpdatedData(final DataTreeModification change) { + InstanceIdentifier gateIID = change.getRootPath().getRootIdentifier(); + //final Gate newGate = (Gate) change.getRootNode().getIdentifier(); // TODO actually support updates // update operation not allowed -- restore the original config object and complain - for (final Map.Entry, Gate> entry : updatedData.entrySet()) { - if (!originalData.containsKey(entry.getKey())) { - logger.error("No original data found for supposedly updated data: {}", entry.getValue()); - continue; - } - - // If this notification is coming from our modification ignore it. - if (updateQueue.contains(entry.getKey())) { - updateQueue.remove(entry.getKey()); - continue; - } - - final Gate originalGate = originalData.get(entry.getKey()); - - // restores the original data - updateQueue.add(entry.getKey()); - mdsalUtils.put(LogicalDatastoreType.CONFIGURATION, entry.getKey(), originalGate); - logger.error("Update not permitted {}", entry.getKey()); + // If this notification is coming from our modification ignore it. + if (updateQueue.contains(gateIID)) { + updateQueue.remove(gateIID); + return; } - } + final Gate originalGate = change.getRootNode().getDataBefore(); + // restores the original data + updateQueue.add(gateIID); + mdsalUtils.put(LogicalDatastoreType.CONFIGURATION, gateIID, originalGate); + logger.error("Update not permitted {}", gateIID); + } @Override - protected void handleRemovedData(final Set> removedPaths, - final Map, Gate> originalData) { - - for (final InstanceIdentifier removedGateIID : removedPaths) { + protected void handleRemovedData(final DataTreeModification change) { + InstanceIdentifier removedGateIID = change.getRootPath().getRootIdentifier(); + final Gate newGate = change.getRootNode().getDataBefore(); - mdsalUtils.delete(LogicalDatastoreType.OPERATIONAL, removedGateIID); + mdsalUtils.delete(LogicalDatastoreType.OPERATIONAL, removedGateIID); - executor.execute(new SubscriberCleaner(removedGateIID)); + executor.execute(new SubscriberCleaner(removedGateIID)); - final String gatePathStr = makeGatePathString(removedGateIID); + final String gatePathStr = makeGatePathString(removedGateIID); - if (gateMap.containsKey(gatePathStr)) { - final Gate thisGate = gateMap.remove(gatePathStr); - final String gateId = thisGate.getGateId(); - final String ccapId = gateCcapMap.remove(gatePathStr); - final Ccap thisCcap = ccapMap.get(ccapId); - final PCMMService service = pcmmServiceMap.get(thisCcap.getCcapId()); - if (service != null) { - service.sendGateDelete(gatePathStr); - logger.info("onDataChanged(): removed QoS gate {} for {}/{}/{}: ", gateId, ccapId, gatePathStr,thisGate); - } else { - logger.warn("Unable to send to locate PCMMService to send gate delete message with CCAP - " - + thisCcap); - } + if (gateMap.containsKey(gatePathStr)) { + final Gate thisGate = gateMap.remove(gatePathStr); + final String gateId = thisGate.getGateId(); + final String ccapId = gateCcapMap.remove(gatePathStr); + final Ccap thisCcap = ccapMap.get(ccapId); + final PCMMService service = pcmmServiceMap.get(thisCcap.getCcapId()); + if (service != null) { + service.sendGateDelete(gatePathStr); + logger.info("onDataChanged(): removed QoS gate {} for {}/{}/{}: ", gateId, ccapId, gatePathStr,thisGate); + } else { + logger.warn("Unable to send to locate PCMMService to send gate delete message with CCAP - " + + thisCcap); } - - } } + @Override + protected void handleInvalidData(final DataTreeModification change, ValidationException validationException){ + // bad data write errors to operational datastore + saveErrors(change, validationException); + } + private String makeGatePathString(InstanceIdentifier iid) { final InstanceIdentifier appIID = iid.firstIdentifierOf(App.class); final AppKey appKey = InstanceIdentifier.keyOf(appIID); @@ -934,7 +857,6 @@ public class PacketcableProvider implements BindingAwareProvider, AutoCloseable, } } - @Override public Future> ccapSetConnection(CcapSetConnectionInput input) { // TODO refactor this method into smaller parts @@ -1378,7 +1300,6 @@ public class PacketcableProvider implements BindingAwareProvider, AutoCloseable, } } } - }