/**
* Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v1.0 which accompanies this distribution,
* and is available at http://www.eclipse.org/legal/epl-v10.html
*/
package org.opendaylight.openflowplugin.applications.statistics.manager;
import java.util.List;
import java.util.UUID;
import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipService;
import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
import org.opendaylight.controller.md.sal.common.api.data.TransactionChainListener;
import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
import org.opendaylight.controller.sal.binding.api.RpcConsumerRegistry;
import org.opendaylight.openflowplugin.applications.statistics.manager.StatPermCollector.StatCapabTypes;
import org.opendaylight.openflowplugin.applications.statistics.manager.impl.StatisticsManagerConfig;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.Meter;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.OpendaylightFlowStatisticsListener;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.OpendaylightFlowTableStatisticsListener;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.transaction.rev150304.TransactionId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.queues.Queue;
import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.OpendaylightGroupStatisticsListener;
import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.OpendaylightMeterStatisticsListener;
import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.OpendaylightPortStatisticsListener;
import org.opendaylight.yang.gen.v1.urn.opendaylight.queue.statistics.rev131216.OpendaylightQueueStatisticsListener;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
/**
* statistics-manager
* org.opendaylight.openflowplugin.applications.statistics.manager
*
* StatisticsManager
* It represent a central point for whole module. Implementation
* StatisticsManager registers all Operation/DS {@link StatNotifyCommiter} and
* Config/DS {@link StatListeningCommiter}, as well as {@link StatPermCollector}
* for statistic collecting and {@link StatRpcMsgManager} as Device RPCs provider.
* In next, StatisticsManager provides all DS contact Transaction services.
*
* @author <a href="mailto:vdemcak@cisco.com">Vaclav Demcak</a>
*
* Created: Aug 27, 2014
*/
public interface StatisticsManager extends AutoCloseable, TransactionChainListener {
/**
* StatDataStoreOperation
* Interface represent functionality to submit changes to DataStore.
* Internal {@link TransactionChainListener} joining all DS commits
* to Set of chained changes for prevent often DataStore touches.
*/
abstract class StatDataStoreOperation {
public enum StatsManagerOperationType {
/**
* Operation will carry out work related to new node addition /
* update
*/
NODE_UPDATE,
/**
* Operation will carry out work related to node removal
*/
NODE_REMOVAL,
/**
* Operation will commit data to the operational data store
*/
DATA_COMMIT_OPER_DS
}
private NodeId nodeId;
private StatsManagerOperationType operationType = StatsManagerOperationType.DATA_COMMIT_OPER_DS;
private UUID nodeUUID;
public StatDataStoreOperation(final StatsManagerOperationType operType, final NodeId id){
if(operType != null){
operationType = operType;
}
nodeId = id;
nodeUUID = generatedUUIDForNode();
}
public final StatsManagerOperationType getType() {
return operationType;
}
public final NodeId getNodeId(){
return nodeId;
}
public UUID getNodeUUID() {
return nodeUUID;
}
/**
* Apply all read / write (put|merge) operation for DataStore
*
* @param tx {@link ReadWriteTransaction}
*/
public abstract void applyOperation(ReadWriteTransaction tx);
protected abstract UUID generatedUUIDForNode();
public InstanceIdentifier<Node> getNodeIdentifier() {
final InstanceIdentifier<Node> nodeIdent = InstanceIdentifier.create(Nodes.class)
.child(Node.class, new NodeKey(nodeId));
return nodeIdent;
}
}
class Pair<L,R> {
private final L left;
private final R right;
public Pair(L left, R right) {
this.left = left;
this.right = right;
}
public L getLeft() { return left; }
public R getRight() { return right; }
@Override
public int hashCode() { return left.hashCode() ^ right.hashCode(); }
@Override
public boolean equals(Object o) {
if (!(o instanceof Pair)) return false;
Pair pairo = (Pair) o;
return this.left.equals(pairo.getLeft()) &&
this.right.equals(pairo.getRight());
}
}
/**
* Method starts whole StatisticManager functionality
*
* @param notifService
* @param rpcRegistry
*/
void start(final NotificationProviderService notifService,
final RpcConsumerRegistry rpcRegistry);
/**
* Method provides read/write DataStore functionality cross applyOperation
* defined in {@link StatDataStoreOperation}
*
* @param inventoryOper - operation for DataStore
*/
void enqueue(final StatDataStoreOperation inventoryOper);
/**
* Method wraps {@link StatisticsManager#isProvidedFlowNodeActive(InstanceIdentifier)} method
* to provide parallel statCollection process for Set of Nodes. So it has to
* identify correct Node Set by NodeIdentifier
*
* @param nodeIdent
*/
boolean isProvidedFlowNodeActive(InstanceIdentifier<Node> nodeIdent);
/**
* Method wraps {@link StatPermCollector}.collectNextStatistics to provide
* parallel statCollection process for Set of Nodes. So it has to
* identify correct Node Set by NodeIdentifier.
*
* @param nodeIdent
*/
void collectNextStatistics(InstanceIdentifier<Node> nodeIdent, TransactionId xid);
/**
* Method wraps {@link StatPermCollector}.connectedNodeRegistration to provide
* parallel statCollection process for Set of Nodes. So it has to
* connect node to new or not full Node statCollector Set.
*
* @param nodeIdent
* @param statTypes
* @param nrOfSwitchTables
*/
void connectedNodeRegistration(InstanceIdentifier<Node> nodeIdent,
List<StatCapabTypes> statTypes, Short nrOfSwitchTables);
/**
* Method wraps {@link StatPermCollector}.disconnectedNodeUnregistration to provide
* parallel statCollection process for Set of Nodes. So it has to identify
* correct collector for disconnect node.
*
* @param nodeIdent
*/
void disconnectedNodeUnregistration(InstanceIdentifier<Node> nodeIdent);
/**
* Method wraps {@link StatPermCollector}.registerAdditionalNodeFeature to provide
* possibility to register additional Node Feature {@link StatCapabTypes} for
* statistics collecting.
*
* @param nodeIdent
* @param statCapab
*/
void registerAdditionalNodeFeature(InstanceIdentifier<Node> nodeIdent, StatCapabTypes statCapab);
/**
* Method wraps {@link StatPermCollector}.unregisterNodeStats to provide
* possibility to unregister Node stats type {@link StatCapabTypes} from
* statistics collecting.
*
* @param nodeIdent
* @param statCapab
*/
void unregisterNodeStats(InstanceIdentifier<Node> nodeIdent, StatCapabTypes statCapab);
/**
* Method provides access to Device RPC methods by wrapped
* internal method. In next {@link StatRpcMsgManager} is registered all
* Multipart device msg response and joining all to be able run all
* collected statistics in one time (easy identification Data for delete)
*
* @return {@link StatRpcMsgManager}
*/
StatRpcMsgManager getRpcMsgManager();
/**
* Define Method : {@link org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode}
* Operational/DS data change listener -> impl. target -> register FlowCapableNode to Statistic Collecting process
* @return {@link StatNodeRegistration}
*/
StatNodeRegistration getNodeRegistrator();
/**
* Define Method : Flow Config/DS data change listener -> impl. target ->
* -> make pair between Config/DS FlowId and Device Flow response Hash
* @return
*/
StatListeningCommiter<Flow, OpendaylightFlowStatisticsListener> getFlowListenComit();
/**
* Define Method : Meter Config/DS data change listener and Operation/DS notify commit
* functionality
* @return
*/
StatListeningCommiter<Meter, OpendaylightMeterStatisticsListener> getMeterListenCommit();
/**
* Define Method : Group Config/DS data change listener and Operation/DS notify commit
* functionality
* @return
*/
StatListeningCommiter<Group, OpendaylightGroupStatisticsListener> getGroupListenCommit();
/**
* Define Method : Queue Config/DS change listener and Operation/DS notify commit functionality
* @return
*/
StatListeningCommiter<Queue, OpendaylightQueueStatisticsListener> getQueueNotifyCommit();
/**
* Define Method : Table Operation/DS notify commit functionality
* @return
*/
StatNotifyCommiter<OpendaylightFlowTableStatisticsListener> getTableNotifCommit();
/**
* Define Method : Port Operation/DS notify commit functionality
* @return
*/
StatNotifyCommiter<OpendaylightPortStatisticsListener> getPortNotifyCommit();
StatisticsManagerConfig getConfiguration();
/**
* A unique UUID is generated with each node added by the statistics manager implementation in order to uniquely
* identify a session.
* @param nodeInstanceIdentifier
*/
UUID getGeneratedUUIDForNode(InstanceIdentifier<Node> nodeInstanceIdentifier);
/*
* Setting entity-ownership-service
*/
void setOwnershipService(EntityOwnershipService ownershipService);
/**
* Getting entity-ownership-service
*/
EntityOwnershipService getOwnershipService();
}