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 extends DataObject> c_key = createdEntry.getKey();
- DataObject c_value = createdEntry.getValue();
- this.add(c_key, c_value);
+ InstanceIdentifier extends DataObject> 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 extends Object> 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 extends Object> 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 extends DataObject> 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 extends DataObject> 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 extends DataObject> identifier,
final DataObject remove);
- protected abstract void update(
- final InstanceIdentifier extends DataObject> 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 extends DataObject> identifier,
final DataObject original, final DataObject update);
- protected abstract void add(
- final InstanceIdentifier extends DataObject> 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 extends DataObject> identifier,
final DataObject add);
}