2 * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
9 package org.opendaylight.controller.md.statistics.manager.impl;
11 import java.util.ArrayList;
12 import java.util.Collections;
13 import java.util.List;
15 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
16 import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
17 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
18 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
19 import org.opendaylight.controller.md.statistics.manager.StatRpcMsgManager.TransactionCacheContainer;
20 import org.opendaylight.controller.md.statistics.manager.StatisticsManager;
21 import org.opendaylight.controller.md.statistics.manager.StatisticsManager.StatDataStoreOperation;
22 import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.transaction.rev131103.TransactionAware;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.transaction.rev131103.TransactionId;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.GroupDescStatsUpdated;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.GroupFeaturesUpdated;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.GroupStatisticsUpdated;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.NodeGroupDescStats;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.NodeGroupDescStatsBuilder;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.NodeGroupFeatures;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.NodeGroupStatistics;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.OpendaylightGroupStatisticsListener;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.group.desc.GroupDescBuilder;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.group.features.GroupFeatures;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.group.features.GroupFeaturesBuilder;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.group.statistics.GroupStatistics;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.group.statistics.GroupStatisticsBuilder;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.desc.stats.reply.GroupDescStats;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.statistics.reply.GroupStats;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.GroupBuilder;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.GroupKey;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
48 import org.opendaylight.yangtools.yang.binding.DataObject;
49 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
50 import org.slf4j.Logger;
51 import org.slf4j.LoggerFactory;
53 import com.google.common.base.Optional;
57 * org.opendaylight.controller.md.statistics.manager.impl
59 * StatListenCommitGroup
60 * Class is a NotifyListener for GroupStatistics and DataChangeListener for Config/DataStore for Group node.
61 * All expected (registered) GroupStatistics will be builded and commit to Operational/DataStore.
62 * DataChangeEven should call create/delete Group in Operational/DS
64 * @author <a href="mailto:vdemcak@cisco.com">Vaclav Demcak</a>
67 public class StatListenCommitGroup extends StatAbstractListenCommit<Group, OpendaylightGroupStatisticsListener>
68 implements OpendaylightGroupStatisticsListener {
70 private static final Logger LOG = LoggerFactory.getLogger(StatListenCommitMeter.class);
72 public StatListenCommitGroup(final StatisticsManager manager, final DataBroker db,
73 final NotificationProviderService nps) {
74 super(manager, db, nps, Group.class);
78 protected OpendaylightGroupStatisticsListener getStatNotificationListener() {
83 protected InstanceIdentifier<Group> getWildCardedRegistrationPath() {
84 return InstanceIdentifier.create(Nodes.class).child(Node.class)
85 .augmentation(FlowCapableNode.class).child(Group.class);
89 public void onGroupDescStatsUpdated(final GroupDescStatsUpdated notification) {
90 final TransactionId transId = notification.getTransactionId();
91 final NodeId nodeId = notification.getId();
92 if ( ! isExpectedStatistics(transId, nodeId)) {
93 LOG.debug("STAT-MANAGER - GroupDescStatsUpdated: unregistred notification detect TransactionId {}", transId);
96 if (notification.isMoreReplies()) {
97 manager.getRpcMsgManager().addNotification(notification, nodeId);
100 final List<GroupDescStats> groupStats = notification.getGroupDescStats() != null
101 ? new ArrayList<>(notification.getGroupDescStats()) : new ArrayList<GroupDescStats>(10);
102 final Optional<TransactionCacheContainer<?>> txContainer = getTransactionCacheContainer(transId, nodeId);
103 if (txContainer.isPresent()) {
104 final List<? extends TransactionAware> cacheNotifs =
105 txContainer.get().getNotifications();
106 for (final TransactionAware notif : cacheNotifs) {
107 if (notif instanceof GroupDescStatsUpdated) {
108 groupStats.addAll(((GroupDescStatsUpdated) notif).getGroupDescStats());
112 final InstanceIdentifier<Node> nodeIdent = InstanceIdentifier
113 .create(Nodes.class).child(Node.class, new NodeKey(nodeId));
114 manager.enqueue(new StatDataStoreOperation() {
116 public void applyOperation(final ReadWriteTransaction tx) {
117 statGroupDescCommit(groupStats, nodeIdent, tx);
118 /* Notification for continue collecting statistics */
119 notifyToCollectNextStatistics(nodeIdent);
125 public void onGroupFeaturesUpdated(final GroupFeaturesUpdated notification) {
126 final TransactionId transId = notification.getTransactionId();
127 final NodeId nodeId = notification.getId();
128 if ( ! isExpectedStatistics(transId, nodeId)) {
129 LOG.debug("STAT-MANAGER - MeterFeaturesUpdated: unregistred notification detect TransactionId {}", transId);
132 if (notification.isMoreReplies()) {
133 manager.getRpcMsgManager().addNotification(notification, nodeId);
136 final Optional<TransactionCacheContainer<?>> txContainer = getTransactionCacheContainer(transId, nodeId);
137 if ( ! txContainer.isPresent()) {
140 final InstanceIdentifier<Node> nodeIdent = InstanceIdentifier
141 .create(Nodes.class).child(Node.class, new NodeKey(nodeId));
143 manager.enqueue(new StatDataStoreOperation() {
145 public void applyOperation(final ReadWriteTransaction tx) {
146 notifyToCollectNextStatistics(nodeIdent);
147 final GroupFeatures stats = new GroupFeaturesBuilder(notification).build();
148 final InstanceIdentifier<GroupFeatures> groupFeatureIdent = nodeIdent
149 .augmentation(NodeGroupFeatures.class).child(GroupFeatures.class);
150 Optional<Node> node = Optional.absent();
152 node = tx.read(LogicalDatastoreType.OPERATIONAL, nodeIdent).checkedGet();
154 catch (final ReadFailedException e) {
155 LOG.debug("Read Operational/DS for Node fail! {}", nodeIdent, e);
157 if (node.isPresent()) {
158 tx.put(LogicalDatastoreType.OPERATIONAL, groupFeatureIdent, stats, true);
165 public void onGroupStatisticsUpdated(final GroupStatisticsUpdated notification) {
166 final TransactionId transId = notification.getTransactionId();
167 final NodeId nodeId = notification.getId();
168 if ( ! isExpectedStatistics(transId, nodeId)) {
169 LOG.debug("STAT-MANAGER - GroupStatisticsUpdated: unregistred notification detect TransactionId {}", transId);
172 if (notification.isMoreReplies()) {
173 manager.getRpcMsgManager().addNotification(notification, nodeId);
176 final List<GroupStats> groupStats = notification.getGroupStats() != null
177 ? new ArrayList<>(notification.getGroupStats()) : new ArrayList<GroupStats>(10);
178 Optional<Group> notifGroup = Optional.absent();
179 final Optional<TransactionCacheContainer<?>> txContainer = getTransactionCacheContainer(transId, nodeId);
180 if (txContainer.isPresent()) {
181 final Optional<? extends DataObject> inputObj = txContainer.get().getConfInput();
182 if (inputObj.isPresent() && inputObj.get() instanceof Group) {
183 notifGroup = Optional.<Group> of((Group)inputObj.get());
185 final List<? extends TransactionAware> cacheNotifs =
186 txContainer.get().getNotifications();
187 for (final TransactionAware notif : cacheNotifs) {
188 if (notif instanceof GroupStatisticsUpdated) {
189 groupStats.addAll(((GroupStatisticsUpdated) notif).getGroupStats());
193 final Optional<Group> group = notifGroup;
194 final InstanceIdentifier<Node> nodeIdent = InstanceIdentifier
195 .create(Nodes.class).child(Node.class, new NodeKey(nodeId));
196 manager.enqueue(new StatDataStoreOperation() {
198 public void applyOperation(final ReadWriteTransaction tx) {
199 /* Notification for continue collecting statistics */
200 if ( ! group.isPresent()) {
201 notifyToCollectNextStatistics(nodeIdent);
203 statGroupCommit(groupStats, nodeIdent, group, tx);
208 private void statGroupCommit(final List<GroupStats> groupStats, final InstanceIdentifier<Node> nodeIdent,
209 final Optional<Group> group, final ReadWriteTransaction trans) {
210 final InstanceIdentifier<FlowCapableNode> fNodeIdent = nodeIdent.augmentation(FlowCapableNode.class);
212 for (final GroupStats groupStat : groupStats) {
213 final GroupStatistics stats = new GroupStatisticsBuilder(groupStat).build();
215 final GroupKey groupKey = new GroupKey(groupStat.getGroupId());
216 final InstanceIdentifier<GroupStatistics> gsIdent = fNodeIdent
217 .child(Group.class,groupKey).augmentation(NodeGroupStatistics.class)
218 .child(GroupStatistics.class);
219 /* Statistics Writing */
220 Optional<FlowCapableNode> fNode = Optional.absent();
222 fNode = trans.read(LogicalDatastoreType.OPERATIONAL, fNodeIdent).checkedGet();
224 catch (final ReadFailedException e) {
225 LOG.debug("Read Operational/DS for FlowCapableNode fail! {}", fNodeIdent, e);
227 if (fNode.isPresent()) {
228 trans.put(LogicalDatastoreType.OPERATIONAL, gsIdent, stats, true);
233 private void statGroupDescCommit(final List<GroupDescStats> groupStats, final InstanceIdentifier<Node> nodeIdent,
234 final ReadWriteTransaction trans) {
235 final InstanceIdentifier<FlowCapableNode> fNodeIdent = nodeIdent.augmentation(FlowCapableNode.class);
237 final List<GroupKey> deviceGroupKeys = new ArrayList<>();
239 for (final GroupDescStats group : groupStats) {
240 if (group.getGroupId() != null) {
241 final GroupBuilder groupBuilder = new GroupBuilder(group);
242 final GroupKey groupKey = new GroupKey(group.getGroupId());
243 final InstanceIdentifier<Group> groupRef = fNodeIdent.child(Group.class,groupKey);
245 final NodeGroupDescStatsBuilder groupDesc= new NodeGroupDescStatsBuilder();
246 groupDesc.setGroupDesc(new GroupDescBuilder(group).build());
247 //Update augmented data
248 groupBuilder.addAugmentation(NodeGroupDescStats.class, groupDesc.build());
249 deviceGroupKeys.add(groupKey);
250 Optional<FlowCapableNode> hashIdUpd = Optional.absent();
252 hashIdUpd = trans.read(LogicalDatastoreType.OPERATIONAL,fNodeIdent).checkedGet();
254 catch (final ReadFailedException e) {
255 LOG.debug("Read Operational/DS for FlowCapableNode fail! {}", fNodeIdent, e);
257 if (hashIdUpd.isPresent()) {
258 trans.put(LogicalDatastoreType.OPERATIONAL, groupRef, groupBuilder.build());
262 /* Delete all not presented Group Nodes */
263 deleteAllNotPresentNode(fNodeIdent, trans, deviceGroupKeys);
266 private void deleteAllNotPresentNode(final InstanceIdentifier<FlowCapableNode> fNodeIdent,
267 final ReadWriteTransaction trans, final List<GroupKey> deviceGroupKeys) {
269 final Optional<FlowCapableNode> fNode = readLatestConfiguration(fNodeIdent);
270 if ( ! fNode.isPresent()) {
271 LOG.trace("Read Operational/DS for FlowCapableNode fail! Node {} doesn't exist.", fNodeIdent);
274 final List<Group> existGroups = fNode.get().getGroup().isEmpty()
275 ? Collections.<Group> emptyList() : fNode.get().getGroup();
276 /* Add all existed groups paths - no updated paths has to be removed */
277 for (final Group group : existGroups) {
278 if (deviceGroupKeys.remove(group.getKey())) {
279 break; // group still exist on device
281 LOG.trace("Group {} has to removed.", group);
282 final InstanceIdentifier<Group> delGroupIdent = fNodeIdent.child(Group.class, group.getKey());
283 Optional<Group> delGroup = Optional.absent();
285 delGroup = trans.read(LogicalDatastoreType.OPERATIONAL, delGroupIdent).checkedGet();
287 catch (final ReadFailedException e) {
288 // NOOP - probably another transaction delete that node
290 if (delGroup.isPresent()) {
291 trans.delete(LogicalDatastoreType.OPERATIONAL, delGroupIdent);