package org.opendaylight.openflowplugin.impl.statistics;
import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import com.google.common.base.Verify;
import com.google.common.collect.Iterators;
import com.google.common.util.concurrent.ListenableFuture;
import io.netty.util.Timeout;
import io.netty.util.TimerTask;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Optional;
+import java.util.concurrent.CancellationException;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.Future;
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.TimeUnit;
+import javax.annotation.CheckForNull;
+import javax.annotation.Nonnull;
import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
+import org.opendaylight.openflowplugin.api.openflow.OFPContext;
import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceState;
import org.opendaylight.openflowplugin.api.openflow.device.handlers.DeviceInitializationPhaseHandler;
import org.opendaylight.openflowplugin.api.openflow.device.handlers.DeviceTerminationPhaseHandler;
import org.opendaylight.openflowplugin.api.openflow.lifecycle.LifecycleConductor;
import org.opendaylight.openflowplugin.api.openflow.rpc.ItemLifeCycleSource;
import org.opendaylight.openflowplugin.api.openflow.statistics.StatisticsContext;
import org.opendaylight.openflowplugin.api.openflow.statistics.StatisticsManager;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorExecutor;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflowplugin.sm.control.rev150812.ChangeStatisticsWorkModeInput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflowplugin.sm.control.rev150812.GetStatisticsWorkModeOutput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflowplugin.sm.control.rev150812.GetStatisticsWorkModeOutputBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import javax.annotation.CheckForNull;
-import javax.annotation.Nonnull;
-import java.util.Iterator;
-import java.util.concurrent.CancellationException;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
-import java.util.concurrent.Future;
-import java.util.concurrent.Semaphore;
-import java.util.concurrent.TimeUnit;
-
public class StatisticsManagerImpl implements StatisticsManager, StatisticsManagerControlService {
private static final Logger LOG = LoggerFactory.getLogger(StatisticsManagerImpl.class);
private static final long DEFAULT_STATS_TIMEOUT_SEC = 50L;
+ private final ConvertorExecutor convertorExecutor;
private DeviceInitializationPhaseHandler deviceInitPhaseHandler;
private DeviceTerminationPhaseHandler deviceTerminPhaseHandler;
- private final ConcurrentMap<NodeId, StatisticsContext> contexts = new ConcurrentHashMap<>();
+ private final ConcurrentMap<DeviceInfo, StatisticsContext> contexts = new ConcurrentHashMap<>();
private static final long basicTimerDelay = 3000;
private static long currentTimerDelay = basicTimerDelay;
public StatisticsManagerImpl(@CheckForNull final RpcProviderRegistry rpcProviderRegistry,
final boolean shuttingDownStatisticsPolling,
- final LifecycleConductor lifecycleConductor) {
+ final LifecycleConductor lifecycleConductor,
+ final ConvertorExecutor convertorExecutor) {
+ this.convertorExecutor = convertorExecutor;
Preconditions.checkArgument(rpcProviderRegistry != null);
this.controlServiceRegistration = Preconditions.checkNotNull(rpcProviderRegistry.addRpcImplementation(
StatisticsManagerControlService.class, this));
}
@Override
- public void onDeviceContextLevelUp(final NodeId nodeId) throws Exception {
-
- final DeviceContext deviceContext = Preconditions.checkNotNull(conductor.getDeviceContext(nodeId));
+ public void onDeviceContextLevelUp(final DeviceInfo deviceInfo) throws Exception {
- final StatisticsContext statisticsContext = new StatisticsContextImpl(nodeId, shuttingDownStatisticsPolling, conductor);
- Verify.verify(contexts.putIfAbsent(nodeId, statisticsContext) == null, "StatisticsCtx still not closed for Node {}", nodeId);
+ final StatisticsContext statisticsContext = new StatisticsContextImpl(deviceInfo, shuttingDownStatisticsPolling, conductor, convertorExecutor);
+ Verify.verify(contexts.putIfAbsent(deviceInfo, statisticsContext) == null, "StatisticsCtx still not closed for Node {}", deviceInfo.getNodeId());
- deviceContext.getDeviceState().setDeviceSynchronized(true);
- deviceInitPhaseHandler.onDeviceContextLevelUp(nodeId);
+ deviceInitPhaseHandler.onDeviceContextLevelUp(deviceInfo);
}
@VisibleForTesting
- void pollStatistics(final DeviceContext deviceContext,
- final StatisticsContext statisticsContext,
- final TimeCounter timeCounter) {
-
- final NodeId nodeId = deviceContext.getDeviceState().getNodeId();
+ void pollStatistics(final DeviceState deviceState,
+ final StatisticsContext statisticsContext,
+ final TimeCounter timeCounter,
+ final DeviceInfo deviceInfo) {
if (!statisticsContext.isSchedulingEnabled()) {
- LOG.debug("Disabling statistics scheduling for device: {}", nodeId);
+ LOG.debug("Disabling statistics scheduling for device: {}", deviceInfo.getNodeId());
return;
}
- if (!deviceContext.getDeviceState().isValid()) {
- LOG.debug("Session is not valid for device: {}", nodeId);
+ if (!deviceState.isValid()) {
+ LOG.debug("Session is not valid for device: {}", deviceInfo.getNodeId());
return;
}
- if (!deviceContext.getDeviceState().isStatisticsPollingEnabled()) {
- LOG.debug("Statistics polling is currently disabled for device: {}", nodeId);
- scheduleNextPolling(deviceContext, statisticsContext, timeCounter);
+ if (!deviceState.isStatisticsPollingEnabled()) {
+ LOG.debug("Statistics polling is currently disabled for device: {}", deviceInfo.getNodeId());
+ scheduleNextPolling(deviceState, deviceInfo, statisticsContext, timeCounter);
return;
}
- LOG.debug("POLLING ALL STATISTICS for device: {}", nodeId);
+ LOG.debug("POLLING ALL STATISTICS for device: {}", deviceInfo.getNodeId());
timeCounter.markStart();
final ListenableFuture<Boolean> deviceStatisticsCollectionFuture = statisticsContext.gatherDynamicData();
Futures.addCallback(deviceStatisticsCollectionFuture, new FutureCallback<Boolean>() {
public void onSuccess(final Boolean o) {
timeCounter.addTimeMark();
calculateTimerDelay(timeCounter);
- scheduleNextPolling(deviceContext, statisticsContext, timeCounter);
+ scheduleNextPolling(deviceState, deviceInfo, statisticsContext, timeCounter);
}
@Override
LOG.trace("Statistics gathering for single node was not successful.. ", throwable);
calculateTimerDelay(timeCounter);
if (throwable instanceof CancellationException) {
- /** This often happens when something wrong with akka or DS, so closing connection will help to restart device **/
- conductor.closeConnection(deviceContext.getDeviceState().getNodeId());
+ /* This often happens when something wrong with akka or DS, so closing connection will help to restart device **/
+ conductor.closeConnection(deviceInfo);
} else {
- scheduleNextPolling(deviceContext, statisticsContext, timeCounter);
+ scheduleNextPolling(deviceState, deviceInfo, statisticsContext, timeCounter);
}
}
});
final long averageTime = TimeUnit.MILLISECONDS.toSeconds(timeCounter.getAverageTimeBetweenMarks());
final long STATS_TIMEOUT_SEC = averageTime > 0 ? 3 * averageTime : DEFAULT_STATS_TIMEOUT_SEC;
- final TimerTask timerTask = new TimerTask() {
-
- @Override
- public void run(final Timeout timeout) throws Exception {
- if (!deviceStatisticsCollectionFuture.isDone()) {
- LOG.info("Statistics collection for node {} still in progress even after {} secs", nodeId, STATS_TIMEOUT_SEC);
- deviceStatisticsCollectionFuture.cancel(true);
- }
+ final TimerTask timerTask = timeout -> {
+ if (!deviceStatisticsCollectionFuture.isDone()) {
+ LOG.info("Statistics collection for node {} still in progress even after {} secs", deviceInfo.getNodeId(), STATS_TIMEOUT_SEC);
+ deviceStatisticsCollectionFuture.cancel(true);
}
};
conductor.newTimeout(timerTask, STATS_TIMEOUT_SEC, TimeUnit.SECONDS);
}
- private void scheduleNextPolling(final DeviceContext deviceContext,
+ private void scheduleNextPolling(final DeviceState deviceState,
+ final DeviceInfo deviceInfo,
final StatisticsContext statisticsContext,
final TimeCounter timeCounter) {
- LOG.debug("SCHEDULING NEXT STATISTICS POLLING for device: {}", deviceContext.getDeviceState().getNodeId());
+ LOG.debug("SCHEDULING NEXT STATISTICS POLLING for device: {}", deviceInfo.getNodeId());
if (!shuttingDownStatisticsPolling) {
- final Timeout pollTimeout = conductor.newTimeout(new TimerTask() {
- @Override
- public void run(final Timeout timeout) throws Exception {
- pollStatistics(deviceContext, statisticsContext, timeCounter);
- }
- }, currentTimerDelay, TimeUnit.MILLISECONDS);
+ final Timeout pollTimeout = conductor.newTimeout(timeout -> pollStatistics(deviceState, statisticsContext, timeCounter, deviceInfo), currentTimerDelay, TimeUnit.MILLISECONDS);
statisticsContext.setPollTimeout(pollTimeout);
}
}
}
@Override
- public void onDeviceContextLevelDown(final DeviceContext deviceContext) {
- final StatisticsContext statisticsContext = contexts.remove(deviceContext.getDeviceState().getNodeId());
+ public void onDeviceContextLevelDown(final DeviceInfo deviceInfo) {
+ final StatisticsContext statisticsContext = contexts.remove(deviceInfo);
if (null != statisticsContext) {
- LOG.trace("Removing device context from stack. No more statistics gathering for device: {}", deviceContext.getDeviceState().getNodeId());
+ LOG.trace("Removing device context from stack. No more statistics gathering for device: {}", deviceInfo.getNodeId());
statisticsContext.close();
}
- deviceTerminPhaseHandler.onDeviceContextLevelDown(deviceContext);
+ deviceTerminPhaseHandler.onDeviceContextLevelDown(deviceInfo);
}
@Override
if (!workMode.equals(targetWorkMode)) {
shuttingDownStatisticsPolling = StatisticsWorkMode.FULLYDISABLED.equals(targetWorkMode);
// iterate through stats-ctx: propagate mode
- for (final StatisticsContext statisticsContext : contexts.values()) {
- final DeviceContext deviceContext = statisticsContext.getDeviceContext();
+ for (Map.Entry<DeviceInfo, StatisticsContext> entry : contexts.entrySet()) {
switch (targetWorkMode) {
case COLLECTALL:
- scheduleNextPolling(deviceContext, statisticsContext, new TimeCounter());
- for (final ItemLifeCycleSource lifeCycleSource : deviceContext.getItemLifeCycleSourceRegistry().getLifeCycleSources()) {
+ scheduleNextPolling(conductor.getDeviceContext(entry.getKey()).getDeviceState(), entry.getKey(), entry.getValue(), new TimeCounter());
+ for (final ItemLifeCycleSource lifeCycleSource : conductor.getDeviceContext(entry.getKey()).getItemLifeCycleSourceRegistry().getLifeCycleSources()) {
lifeCycleSource.setItemLifecycleListener(null);
}
break;
case FULLYDISABLED:
- final Optional<Timeout> pollTimeout = statisticsContext.getPollTimeout();
+ final Optional<Timeout> pollTimeout = entry.getValue().getPollTimeout();
if (pollTimeout.isPresent()) {
pollTimeout.get().cancel();
}
- for (final ItemLifeCycleSource lifeCycleSource : deviceContext.getItemLifeCycleSourceRegistry().getLifeCycleSources()) {
- lifeCycleSource.setItemLifecycleListener(statisticsContext.getItemLifeCycleListener());
+ for (final ItemLifeCycleSource lifeCycleSource : conductor.getDeviceContext(entry.getKey()).getItemLifeCycleSourceRegistry().getLifeCycleSources()) {
+ lifeCycleSource.setItemLifecycleListener(entry.getValue().getItemLifeCycleListener());
}
break;
default:
}
@Override
- public void startScheduling(final NodeId nodeId) {
+ public void startScheduling(final DeviceInfo deviceInfo) {
if (shuttingDownStatisticsPolling) {
- LOG.info("Statistics are shut down for device: {}", nodeId);
+ LOG.info("Statistics are shut down for device: {}", deviceInfo.getNodeId());
return;
}
- final StatisticsContext statisticsContext = contexts.get(nodeId);
+ final StatisticsContext statisticsContext = contexts.get(deviceInfo);
if (statisticsContext == null) {
- LOG.warn("Statistics context not found for device: {}", nodeId);
+ LOG.warn("Statistics context not found for device: {}", deviceInfo.getNodeId());
return;
}
if (statisticsContext.isSchedulingEnabled()) {
- LOG.debug("Statistics scheduling is already enabled for device: {}", nodeId);
+ LOG.debug("Statistics scheduling is already enabled for device: {}", deviceInfo.getNodeId());
return;
}
- LOG.info("Scheduling statistics poll for device: {}", nodeId);
- final DeviceContext deviceContext = conductor.getDeviceContext(nodeId);
-
- if (deviceContext == null) {
- LOG.warn("Device context not found for device: {}", nodeId);
- return;
- }
+ LOG.info("Scheduling statistics poll for device: {}", deviceInfo.getNodeId());
statisticsContext.setSchedulingEnabled(true);
- scheduleNextPolling(deviceContext, statisticsContext, new TimeCounter());
+ scheduleNextPolling(conductor.getDeviceContext(deviceInfo).getDeviceState(), deviceInfo, statisticsContext, new TimeCounter());
}
@Override
- public void stopScheduling(final NodeId nodeId) {
- LOG.debug("Stopping statistics scheduling for device: {}", nodeId);
- final StatisticsContext statisticsContext = contexts.get(nodeId);
+ public void stopScheduling(final DeviceInfo deviceInfo) {
+ LOG.debug("Stopping statistics scheduling for device: {}", deviceInfo.getNodeId());
+ final StatisticsContext statisticsContext = contexts.get(deviceInfo);
if (statisticsContext == null) {
- LOG.warn("Statistics context not found for device: {}", nodeId);
+ LOG.warn("Statistics context not found for device: {}", deviceInfo.getNodeId());
return;
}
public void setDeviceTerminationPhaseHandler(final DeviceTerminationPhaseHandler handler) {
this.deviceTerminPhaseHandler = handler;
}
+
+ @Override
+ public <T extends OFPContext> T gainContext(DeviceInfo deviceInfo) {
+ return (T) contexts.get(deviceInfo);
+ }
}