X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=applications%2Fforwardingrules-sync%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fopenflowplugin%2Fapplications%2Ffrsync%2Fimpl%2FSimplifiedOperationalListener.java;h=b633bb07b71f929362e8928ab45f5c641d5944a1;hb=refs%2Fchanges%2F34%2F46834%2F1;hp=c5aaf8def34d70a4d11c88d2b0f3ee3e46154ca9;hpb=84e650a6e5beed21e2855355f7bc79c9b8bdd526;p=openflowplugin.git diff --git a/applications/forwardingrules-sync/src/main/java/org/opendaylight/openflowplugin/applications/frsync/impl/SimplifiedOperationalListener.java b/applications/forwardingrules-sync/src/main/java/org/opendaylight/openflowplugin/applications/frsync/impl/SimplifiedOperationalListener.java index c5aaf8def3..b633bb07b7 100644 --- a/applications/forwardingrules-sync/src/main/java/org/opendaylight/openflowplugin/applications/frsync/impl/SimplifiedOperationalListener.java +++ b/applications/forwardingrules-sync/src/main/java/org/opendaylight/openflowplugin/applications/frsync/impl/SimplifiedOperationalListener.java @@ -15,8 +15,9 @@ import java.text.SimpleDateFormat; import java.util.Collection; import java.util.Date; import java.util.List; +import java.util.Objects; +import javax.annotation.Nonnull; import org.opendaylight.controller.md.sal.binding.api.DataObjectModification; -import org.opendaylight.controller.md.sal.binding.api.DataObjectModification.ModificationType; import org.opendaylight.controller.md.sal.binding.api.DataTreeModification; import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; import org.opendaylight.openflowplugin.applications.frsync.SyncReactor; @@ -43,9 +44,9 @@ import org.slf4j.LoggerFactory; * Listens to operational changes and starts reconciliation through {@link SyncReactor} when necessary. */ public class SimplifiedOperationalListener extends AbstractFrmSyncListener { + private static final Logger LOG = LoggerFactory.getLogger(SimplifiedOperationalListener.class); public static final String DATE_AND_TIME_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSSXXX"; - private final SyncReactor reactor; private final FlowCapableNodeSnapshotDao operationalSnapshot; private final FlowCapableNodeDao configDao; @@ -65,103 +66,75 @@ public class SimplifiedOperationalListener extends AbstractFrmSyncListener } @Override - public void onDataTreeChanged(Collection> modifications) { - LOG.trace("Operational changes: {}", modifications.size()); + public void onDataTreeChanged(@Nonnull final Collection> modifications) { super.onDataTreeChanged(modifications); } /** - * Update cache, register for device masterhip when device connected and start reconciliation if device + * Update cache, register for device mastership when device connected and start reconciliation if device * is registered and actual modification is consistent.Skip the event otherwise. - * @throws InterruptedException from syncup */ protected Optional> processNodeModification( - DataTreeModification modification) throws InterruptedException { + final DataTreeModification modification) { + Optional> result; final NodeId nodeId = ModificationUtil.nodeId(modification); - updateCache(modification); - - if (isAdd(modification) || isAddLogical(modification)) { - deviceMastershipManager.onDeviceConnected(nodeId); - } - - if (reconciliationRegistry.isRegistered(nodeId) && isConsistentForReconcile(modification)) { - return reconciliation(modification); - } else { - return skipModification(modification); - } - } + final DataObjectModification nodeModification = modification.getRootNode(); - /** - * Remove if delete. Update only if FlowCapableNode Augmentation modified. - * Unregister for device mastership. - * @param modification Datastore modification - */ - private void updateCache(DataTreeModification modification) { - NodeId nodeId = ModificationUtil.nodeId(modification); - if (isDelete(modification) || isDeleteLogical(modification)) { + if (isDelete(nodeModification) || isDeleteLogical(nodeModification)) { operationalSnapshot.updateCache(nodeId, Optional.absent()); deviceMastershipManager.onDeviceDisconnected(nodeId); - return; + result = skipModification(modification); + } else { + operationalSnapshot.updateCache(nodeId, Optional.fromNullable(ModificationUtil.flowCapableNodeAfter(modification))); + + final boolean isAdd = isAdd(nodeModification) || isAddLogical(nodeModification); + + if (isAdd) { + deviceMastershipManager.onDeviceConnected(nodeId); + } + + // if node is registered for reconcile we need consistent data from operational DS (skip partial collections) + // but we can accept first modification since all statistics are intentionally collected in one step on startup + if (reconciliationRegistry.isRegistered(nodeId) && (isAdd || isConsistentForReconcile(modification))) { + result = reconciliation(modification); + } else { + result = skipModification(modification); + } } - operationalSnapshot.updateCache(nodeId, Optional.fromNullable(ModificationUtil.flowCapableNodeAfter(modification))); + return result; } - private Optional> skipModification(DataTreeModification modification) { - LOG.trace("Skipping operational modification: {}, before {}, after {}", - ModificationUtil.nodeIdValue(modification), - modification.getRootNode().getDataBefore() == null ? "null" : "nonnull", - modification.getRootNode().getDataAfter() == null ? "null" : "nonnull"); + private Optional> skipModification(final DataTreeModification modification) { + if (LOG.isTraceEnabled()) { + LOG.trace("Skipping operational modification: {}, before {}, after {}", + ModificationUtil.nodeIdValue(modification), + modification.getRootNode().getDataBefore() == null ? "null" : "nonnull", + modification.getRootNode().getDataAfter() == null ? "null" : "nonnull"); + } return Optional.absent(); } - /** - * ModificationType.DELETE. - */ - private boolean isDelete(DataTreeModification modification) { - if (ModificationType.DELETE == modification.getRootNode().getModificationType()) { - LOG.trace("Delete {} (physical)", ModificationUtil.nodeIdValue(modification)); - return true; - } - - return false; + private boolean isDelete(final DataObjectModification nodeModification) { + return Objects.nonNull(nodeModification.getDataBefore()) && Objects.isNull(nodeModification.getDataAfter()); } /** * All connectors disappeared from operational store (logical delete). */ - private boolean isDeleteLogical(DataTreeModification modification) { - final DataObjectModification rootNode = modification.getRootNode(); - if (!safeConnectorsEmpty(rootNode.getDataBefore()) && safeConnectorsEmpty(rootNode.getDataAfter())) { - LOG.trace("Delete {} (logical)", ModificationUtil.nodeIdValue(modification)); - return true; - } + private boolean isDeleteLogical(final DataObjectModification nodeModification) { + return !safeConnectorsEmpty(nodeModification.getDataBefore()) && safeConnectorsEmpty(nodeModification.getDataAfter()); - return false; } - private boolean isAdd(DataTreeModification modification) { - final DataObjectModification rootNode = modification.getRootNode(); - final Node dataAfter = rootNode.getDataAfter(); - final Node dataBefore = rootNode.getDataBefore(); - - final boolean nodeAppearedInOperational = dataBefore == null && dataAfter != null; - if (nodeAppearedInOperational) { - LOG.trace("Add {} (physical)", ModificationUtil.nodeIdValue(modification)); - } - return nodeAppearedInOperational; + private boolean isAdd(final DataObjectModification nodeModification) { + return Objects.isNull(nodeModification.getDataBefore()) && Objects.nonNull(nodeModification.getDataAfter()); } /** * All connectors appeared in operational store (logical add). */ - private boolean isAddLogical(DataTreeModification modification) { - final DataObjectModification rootNode = modification.getRootNode(); - if (safeConnectorsEmpty(rootNode.getDataBefore()) && !safeConnectorsEmpty(rootNode.getDataAfter())) { - LOG.trace("Add {} (logical)", ModificationUtil.nodeIdValue(modification)); - return true; - } - - return false; + private boolean isAddLogical(final DataObjectModification nodeModification) { + return safeConnectorsEmpty(nodeModification.getDataBefore()) && !safeConnectorsEmpty(nodeModification.getDataAfter()); } /** @@ -169,9 +142,8 @@ public class SimplifiedOperationalListener extends AbstractFrmSyncListener * configuration (coming from operational) should be calculated and sent to device. * @param modification from DS * @return optional syncup future - * @throws InterruptedException from syncup */ - private Optional> reconciliation(DataTreeModification modification) throws InterruptedException { + private Optional> reconciliation(final DataTreeModification modification) { final NodeId nodeId = ModificationUtil.nodeId(modification); final Optional nodeConfiguration = configDao.loadByNodeId(nodeId); @@ -191,7 +163,13 @@ public class SimplifiedOperationalListener extends AbstractFrmSyncListener } } - private boolean isConsistentForReconcile(DataTreeModification modification) { + /** + * Check if modification is consistent for reconciliation. We need fresh data, which means that current statistics + * were collected after registration for reconcile and whole bunch of statistics was collected successfully. + * @param modification from DS + * @return status of modification + */ + private boolean isConsistentForReconcile(final DataTreeModification modification) { final NodeId nodeId = PathUtil.digNodeId(modification.getRootPath().getRootIdentifier()); final FlowCapableStatisticsGatheringStatus gatheringStatus = modification.getRootNode().getDataAfter() .getAugmentation(FlowCapableStatisticsGatheringStatus.class); @@ -222,13 +200,13 @@ public class SimplifiedOperationalListener extends AbstractFrmSyncListener return true; } } catch (ParseException e) { - LOG.error("Timestamp parsing error {}", e); + LOG.warn("Timestamp parsing error {}", e); } LOG.debug("Fresh operational not present: {}", nodeId.getValue()); return false; } - private static boolean safeConnectorsEmpty(Node node) { + private static boolean safeConnectorsEmpty(final Node node) { if (node == null) { return true; } @@ -240,5 +218,4 @@ public class SimplifiedOperationalListener extends AbstractFrmSyncListener public LogicalDatastoreType dsType() { return LogicalDatastoreType.OPERATIONAL; } - }