2 * Copyright (c) 2017 AT&T Intellectual Property. 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
8 package org.opendaylight.bgpcep.pcep.topology.stats.provider;
10 import static java.util.Objects.requireNonNull;
11 import static java.util.concurrent.TimeUnit.SECONDS;
13 import com.google.common.util.concurrent.FutureCallback;
14 import com.google.common.util.concurrent.MoreExecutors;
15 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
16 import java.util.HashMap;
18 import java.util.TimerTask;
19 import java.util.concurrent.ExecutionException;
20 import java.util.concurrent.Executors;
21 import java.util.concurrent.ScheduledExecutorService;
22 import java.util.concurrent.ScheduledFuture;
23 import java.util.concurrent.atomic.AtomicBoolean;
24 import org.checkerframework.checker.lock.qual.GuardedBy;
25 import org.eclipse.jdt.annotation.NonNull;
26 import org.opendaylight.bgpcep.pcep.topology.spi.stats.TopologySessionStatsRegistry;
27 import org.opendaylight.mdsal.binding.api.DataBroker;
28 import org.opendaylight.mdsal.binding.api.Transaction;
29 import org.opendaylight.mdsal.binding.api.TransactionChain;
30 import org.opendaylight.mdsal.binding.api.TransactionChainListener;
31 import org.opendaylight.mdsal.binding.api.WriteTransaction;
32 import org.opendaylight.mdsal.common.api.CommitInfo;
33 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.stats.rev171113.PcepSessionState;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.stats.rev171113.pcep.session.state.grouping.PcepSessionStateBuilder;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.stats.rev181109.PcepTopologyNodeStatsAug;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.stats.rev181109.PcepTopologyNodeStatsAugBuilder;
38 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
39 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
40 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
41 import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
42 import org.slf4j.Logger;
43 import org.slf4j.LoggerFactory;
45 public final class TopologyStatsProviderImpl implements TransactionChainListener,
46 TopologySessionStatsRegistry, AutoCloseable {
48 private static final Logger LOG = LoggerFactory.getLogger(TopologyStatsProviderImpl.class);
50 private final Map<KeyedInstanceIdentifier<Node, NodeKey>, PcepSessionState> statsMap = new HashMap<>();
51 private final DataBroker dataBroker;
52 private final int timeout;
53 private TransactionChain transactionChain;
54 private ScheduledFuture<?> scheduleTask;
55 private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
56 private final AtomicBoolean closed = new AtomicBoolean(false);
58 public TopologyStatsProviderImpl(final @NonNull DataBroker dataBroker, final int timeout) {
59 this.dataBroker = requireNonNull(dataBroker);
60 this.timeout = timeout;
63 public synchronized void init() {
64 LOG.info("Initializing TopologyStatsProvider service.");
65 this.transactionChain = this.dataBroker.createMergingTransactionChain(this);
66 final TimerTask task = new TimerTask() {
73 this.scheduleTask = this.scheduler.scheduleAtFixedRate(task, 0, this.timeout, SECONDS);
76 @SuppressWarnings("checkstyle:IllegalCatch")
77 @SuppressFBWarnings(value = "UPM_UNCALLED_PRIVATE_METHOD",
78 justification = "https://github.com/spotbugs/spotbugs/issues/811")
79 private synchronized void updatePcepStats() {
80 final WriteTransaction tx = TopologyStatsProviderImpl.this.transactionChain.newWriteOnlyTransaction();
83 for (final Map.Entry<KeyedInstanceIdentifier<Node, NodeKey>, PcepSessionState> entry
84 : this.statsMap.entrySet()) {
85 final PcepTopologyNodeStatsAug nodeStatsAug = new PcepTopologyNodeStatsAugBuilder()
86 .setPcepSessionState(new PcepSessionStateBuilder(entry.getValue()).build()).build();
87 final InstanceIdentifier<PcepTopologyNodeStatsAug> statId =
88 entry.getKey().augmentation(PcepTopologyNodeStatsAug.class);
89 tx.put(LogicalDatastoreType.OPERATIONAL, statId, nodeStatsAug);
91 tx.commit().addCallback(new FutureCallback<CommitInfo>() {
93 public void onSuccess(final CommitInfo result) {
94 LOG.debug("Successfully committed Topology stats update");
98 public void onFailure(final Throwable ex) {
99 LOG.error("Failed to commit Topology stats update", ex);
101 }, MoreExecutors.directExecutor());
102 } catch (final Exception e) {
103 LOG.warn("Failed to prepare Tx for PCEP stats update", e);
109 public synchronized void close() throws Exception {
110 if (closed.compareAndSet(false, true)) {
111 LOG.info("Closing TopologyStatsProvider service.");
112 this.scheduleTask.cancel(true);
113 final WriteTransaction wTx = this.transactionChain.newWriteOnlyTransaction();
114 for (final KeyedInstanceIdentifier<Node, NodeKey> statId : this.statsMap.keySet()) {
115 wTx.delete(LogicalDatastoreType.OPERATIONAL, statId);
118 this.statsMap.clear();
119 this.transactionChain.close();
120 this.scheduler.shutdown();
125 public synchronized void onTransactionChainFailed(final TransactionChain chain,
126 final Transaction transaction, final Throwable cause) {
127 LOG.error("Transaction chain {} failed for tx {}",
128 chain, transaction != null ? transaction.getIdentifier() : null, cause);
131 transactionChain.close();
132 transactionChain = dataBroker.createMergingTransactionChain(this);
137 public synchronized void onTransactionChainSuccessful(final TransactionChain chain) {
138 LOG.debug("Transaction chain {} successful.", chain);
142 public synchronized void bind(final KeyedInstanceIdentifier<Node, NodeKey> nodeId,
143 final PcepSessionState sessionState) {
144 this.statsMap.put(nodeId, sessionState);
148 public synchronized void unbind(final KeyedInstanceIdentifier<Node, NodeKey> nodeId) {
149 this.statsMap.remove(nodeId);
150 final WriteTransaction wTx = this.transactionChain.newWriteOnlyTransaction();
151 wTx.delete(LogicalDatastoreType.OPERATIONAL, nodeId);
154 } catch (final InterruptedException | ExecutionException e) {
155 LOG.warn("Failed to remove Pcep Node stats {}.", nodeId.getKey().getNodeId(), e);