final NodeId nodeId = ModificationUtil.nodeId(modification);
updateCache(modification);
- if (isAdd(modification) || isAddLogical(modification)) {
+ final boolean isAdd = isAdd(modification) || isAddLogical(modification);
+
+ if (isAdd) {
deviceMastershipManager.onDeviceConnected(nodeId);
}
- if (reconciliationRegistry.isRegistered(nodeId) && isConsistentForReconcile(modification)) {
+ // 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))) {
return reconciliation(modification);
} else {
return skipModification(modification);
return Optional.absent();
}
- /**
- * ModificationType.DELETE.
- */
private boolean isDelete(final DataTreeModification<Node> modification) {
return ModificationType.DELETE == modification.getRootNode().getModificationType();
}
}
}
+ /**
+ * 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<Node> modification) {
final NodeId nodeId = PathUtil.digNodeId(modification.getRootPath().getRootIdentifier());
final FlowCapableStatisticsGatheringStatus gatheringStatus = modification.getRootNode().getDataAfter()
public Date register(NodeId nodeId) {
Date timestamp = new Date();
registration.put(nodeId, timestamp);
- LOG.debug("Registered for next consistent operational: {}", nodeId.getValue());
+ LOG.debug("Registered for reconciliation: {}", nodeId.getValue());
// TODO elicit statistics gathering if not running actually
return timestamp;
}
public Date unregisterIfRegistered(NodeId nodeId) {
Date timestamp = registration.remove(nodeId);
if (timestamp != null) {
- LOG.debug("Unregistered for next consistent operational: {}", nodeId.getValue());
+ LOG.debug("Unregistered for reconciliation: {}", nodeId.getValue());
}
return timestamp;
}
Mockito.verify(roTx).close();
}
+
+ @Test
+ public void testOnDataTreeChangedReconcileAndFreshOperationalNotPresentButAdd() throws ParseException {
+ Mockito.when(reconciliationRegistry.isRegistered(NODE_ID)).thenReturn(true);
+ operationalAdd();
+ prepareFreshOperational(false);
+ final SyncupEntry syncupEntry = loadConfigDSAndPrepareSyncupEntry(configNode, configDS, fcOperationalNode, operationalDS);
+
+ nodeListenerOperational.onDataTreeChanged(Collections.singleton(dataTreeModification));
+
+ Mockito.verify(reactor).syncup(fcNodePath, syncupEntry);
+ Mockito.verify(roTx).close();
+ }
+
@Test
public void testOnDataTreeChangedReconcileAndConfigNotPresent() throws Exception {
// Related to bug 5920 -> https://bugs.opendaylight.org/show_bug.cgi?id=5920