X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?p=controller.git;a=blobdiff_plain;f=opendaylight%2Fmd-sal%2Fforwardingrules-manager%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fcontroller%2Ffrm%2FAbstractChangeListener.java;h=130c096deb9545bdc4407eb146082d0dd44b738d;hp=c8a7f01e132b519c5f522554faa7e2dd8bfd2ae7;hb=3bad057a3d83945a7e23113aacbdba6ba9cb5d97;hpb=aebab42f1b08f22037ce725fd852d79584d09109 diff --git a/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/AbstractChangeListener.java b/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/AbstractChangeListener.java index c8a7f01e13..130c096deb 100644 --- a/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/AbstractChangeListener.java +++ b/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/AbstractChangeListener.java @@ -9,67 +9,89 @@ package org.opendaylight.controller.frm; import java.util.HashSet; import java.util.Map; -import java.util.Set; import java.util.Map.Entry; +import java.util.Set; +import java.util.concurrent.ExecutionException; import java.util.concurrent.atomic.AtomicLong; -import org.opendaylight.controller.md.sal.common.api.data.DataChangeEvent; -import org.opendaylight.controller.sal.binding.api.data.DataChangeListener; +import org.opendaylight.controller.md.sal.binding.api.DataChangeListener; +import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction; +import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent; +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node; import org.opendaylight.yangtools.yang.binding.DataObject; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** + * AbstractChangeListner implemented basic {@link AsyncDataChangeEvent} processing for + * flow node subDataObject (flows, groups and meters). * * @author Vaclav Demcak * */ public abstract class AbstractChangeListener implements DataChangeListener { + private final static Logger LOG = LoggerFactory.getLogger(AbstractChangeListener.class); + private final AtomicLong txNum = new AtomicLong(); private String transactionId; @Override - public void onDataChanged(DataChangeEvent, DataObject> changeEvent) { + public void onDataChanged(final AsyncDataChangeEvent, DataObject> changeEvent) { this.transactionId = this.newTransactionIdentifier().toString(); - + /* All DataObjects for create */ final Set, DataObject>> createdEntries = - changeEvent.getCreatedConfigurationData().entrySet(); - final Set, DataObject>> updatedEntries = - new HashSet, DataObject>>(); - + changeEvent.getCreatedData().entrySet(); + /* All DataObjects for updates - init HashSet */ + final Set, DataObject>> updatedEntries = new HashSet<>(); + /* Filtered DataObject for update processing only */ Set, DataObject>> updateConfigEntrySet = - changeEvent.getUpdatedConfigurationData().entrySet(); + changeEvent.getUpdatedData().entrySet(); updatedEntries.addAll(updateConfigEntrySet); updatedEntries.removeAll(createdEntries); - + /* All DataObjects for remove */ final Set> removeEntriesInstanceIdentifiers = - changeEvent.getRemovedConfigurationData(); - + changeEvent.getRemovedPaths(); + /* Create DataObject processing (send to device) */ for (final Entry, DataObject> createdEntry : createdEntries) { - InstanceIdentifier c_key = createdEntry.getKey(); - DataObject c_value = createdEntry.getValue(); - this.add(c_key, c_value); + InstanceIdentifier entryKey = createdEntry.getKey(); + DataObject entryValue = createdEntry.getValue(); + if (preconditionForChange(entryKey, entryValue, null)) { + this.add(entryKey, entryValue); + } } for (final Entry, DataObject> updatedEntrie : updatedEntries) { Map, DataObject> origConfigData = - changeEvent.getOriginalConfigurationData(); - - InstanceIdentifier u_key = updatedEntrie.getKey(); - final DataObject originalFlow = origConfigData.get(u_key); - final DataObject updatedFlow = updatedEntrie.getValue(); - this.update(u_key, originalFlow, updatedFlow); + changeEvent.getOriginalData(); + + InstanceIdentifier entryKey = updatedEntrie.getKey(); + final DataObject original = origConfigData.get(entryKey); + final DataObject updated = updatedEntrie.getValue(); + if (preconditionForChange(entryKey, original, updated)) { + this.update(entryKey, original, updated); + } } for (final InstanceIdentifier instanceId : removeEntriesInstanceIdentifiers) { Map, DataObject> origConfigData = - changeEvent.getOriginalConfigurationData(); + changeEvent.getOriginalData(); final DataObject removeValue = origConfigData.get(instanceId); - this.remove(instanceId, removeValue); + if (preconditionForChange(instanceId, removeValue, null)) { + this.remove(instanceId, removeValue); + } } } + /** + * Method returns generated transaction ID, which is unique for + * every transaction. ID is composite from prefix ("DOM") and unique number. + * + * @return String transactionID + */ public String getTransactionId() { return this.transactionId; } @@ -78,17 +100,74 @@ public abstract class AbstractChangeListener implements DataChangeListener { return "DOM-" + txNum.getAndIncrement(); } - protected abstract void validate() throws IllegalStateException; - - protected abstract void remove( + /** + * Method check all local preconditions for apply relevant changes. + * + * @param InstanceIdentifier identifier - the whole path to DataObject + * @param DataObject original - original DataObject (for update) + * or relevant DataObject (add/delete operations) + * @param DataObject update - changed DataObject (contain updates) + * or should be null for (add/delete operations) + * + * @return boolean - applicable + */ + protected abstract boolean preconditionForChange( final InstanceIdentifier identifier, + final DataObject original, final DataObject update); + + /** + * Method checks the node data path in DataStore/OPERATIONAL because + * without the Node Identifier in DataStore/OPERATIONAL, device + * is not connected and device pre-configuration is allowed only. + * + * @param InstanceIdentifier identifier - could be whole path to DataObject, + * but parent Node.class InstanceIdentifier is used for a check only + * + * @return boolean - is the Node available in DataStore/OPERATIONAL (is connected) + */ + protected boolean isNodeAvailable(final InstanceIdentifier identifier, + final ReadOnlyTransaction readTrans) { + final InstanceIdentifier nodeInstanceId = identifier.firstIdentifierOf(Node.class); + try { + return readTrans.read(LogicalDatastoreType.OPERATIONAL, nodeInstanceId).get().isPresent(); + } + catch (InterruptedException | ExecutionException e) { + LOG.error("Unexpected exception by reading Node ".concat(nodeInstanceId.toString()), e); + return false; + } + finally { + readTrans.close(); + } + } + + /** + * Method removes DataObject which is identified by InstanceIdentifier + * from device. + * + * @param InstanceIdentifier identifier - the whole path to DataObject + * @param DataObject remove - DataObject for removing + */ + protected abstract void remove(final InstanceIdentifier identifier, final DataObject remove); - protected abstract void update( - final InstanceIdentifier identifier, + /** + * Method updates the original DataObject to the update DataObject + * in device. Both are identified by same InstanceIdentifier + * + * @param InstanceIdentifier identifier - the whole path to DataObject + * @param DataObject original - original DataObject (for update) + * @param DataObject update - changed DataObject (contain updates) + */ + protected abstract void update(final InstanceIdentifier identifier, final DataObject original, final DataObject update); - protected abstract void add( - final InstanceIdentifier identifier, + /** + * Method adds the DataObject which is identified by InstanceIdentifier + * to device. + * + * @param InstanceIdentifier identifier - the whole path to new DataObject + * @param DataObject add - new DataObject + */ + protected abstract void add(final InstanceIdentifier identifier, final DataObject add); }