Migrate deprecated submit() to commit() under PCEP
[bgpcep.git] / pcep / topology / topology-stats / src / main / java / org / opendaylight / bgpcep / pcep / topology / stats / provider / TopologyStatsProviderImpl.java
1 /*
2  * Copyright (c) 2017 AT&T Intellectual Property. All rights reserved.
3  *
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
7  */
8
9 package org.opendaylight.bgpcep.pcep.topology.stats.provider;
10
11 import static java.util.Objects.requireNonNull;
12 import static java.util.concurrent.TimeUnit.SECONDS;
13
14 import com.google.common.util.concurrent.FutureCallback;
15 import com.google.common.util.concurrent.MoreExecutors;
16 import java.util.HashMap;
17 import java.util.Map;
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 javax.annotation.Nonnull;
25 import javax.annotation.concurrent.GuardedBy;
26 import org.opendaylight.bgpcep.pcep.topology.spi.stats.TopologySessionStatsRegistry;
27 import org.opendaylight.controller.md.sal.binding.api.BindingTransactionChain;
28 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
29 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
30 import org.opendaylight.controller.md.sal.common.api.data.AsyncTransaction;
31 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
32 import org.opendaylight.controller.md.sal.common.api.data.TransactionChain;
33 import org.opendaylight.controller.md.sal.common.api.data.TransactionChainListener;
34 import org.opendaylight.mdsal.common.api.CommitInfo;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.stats.rev171113.PcepSessionState;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.stats.rev171113.pcep.session.state.grouping.PcepSessionStateBuilder;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.stats.rev171113.PcepTopologyNodeStatsAug;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.stats.rev171113.PcepTopologyNodeStatsAugBuilder;
39 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
40 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
41 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
42 import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
43 import org.slf4j.Logger;
44 import org.slf4j.LoggerFactory;
45
46 public final class TopologyStatsProviderImpl implements TransactionChainListener,
47         TopologySessionStatsRegistry, AutoCloseable {
48
49     private static final Logger LOG = LoggerFactory.getLogger(TopologyStatsProviderImpl.class);
50     @GuardedBy("this")
51     private final Map<KeyedInstanceIdentifier<Node, NodeKey>, PcepSessionState> statsMap = new HashMap<>();
52     private final DataBroker dataBroker;
53     private final int timeout;
54     private BindingTransactionChain transactionChain;
55     private ScheduledFuture<?> scheduleTask;
56     private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
57     private final AtomicBoolean closed = new AtomicBoolean(false);
58
59     public TopologyStatsProviderImpl(@Nonnull final DataBroker dataBroker, final int timeout) {
60         this.dataBroker = requireNonNull(dataBroker);
61         this.timeout = timeout;
62     }
63
64     public synchronized void init() {
65         LOG.info("Initializing TopologyStatsProvider service.", this);
66         this.transactionChain = this.dataBroker.createTransactionChain(this);
67         final TimerTask task = new TimerTask() {
68             @Override
69             public void run() {
70                 updatePcepStats();
71             }
72         };
73
74         this.scheduleTask = this.scheduler.scheduleAtFixedRate(task, 0, this.timeout, SECONDS);
75     }
76
77     @SuppressWarnings("checkstyle:IllegalCatch")
78     private synchronized void updatePcepStats() {
79         final WriteTransaction tx = TopologyStatsProviderImpl.this.transactionChain.newWriteOnlyTransaction();
80
81         try {
82             for (final Map.Entry<KeyedInstanceIdentifier<Node, NodeKey>, PcepSessionState> entry
83                     : this.statsMap.entrySet()) {
84                 final PcepTopologyNodeStatsAug nodeStatsAug = new PcepTopologyNodeStatsAugBuilder()
85                         .setPcepSessionState(new PcepSessionStateBuilder(entry.getValue()).build()).build();
86                 final InstanceIdentifier<PcepTopologyNodeStatsAug> statId =
87                         entry.getKey().augmentation(PcepTopologyNodeStatsAug.class);
88                 tx.put(LogicalDatastoreType.OPERATIONAL, statId, nodeStatsAug);
89             }
90             tx.commit().addCallback(new FutureCallback<CommitInfo>() {
91                 @Override
92                 public void onSuccess(CommitInfo result) {
93                     LOG.debug("Successfully committed Topology stats update");
94                 }
95
96                 @Override
97                 public void onFailure(Throwable ex) {
98                     LOG.error("Failed to commit Topology stats update", ex);
99                 }
100             }, MoreExecutors.directExecutor());
101         } catch (final Exception e) {
102             LOG.warn("Failed to prepare Tx for BGP stats update", e);
103             tx.cancel();
104         }
105     }
106
107     @Override
108     public synchronized void close() throws Exception {
109         if (closed.compareAndSet(false, true)) {
110             LOG.info("Closing TopologyStatsProvider service.", this);
111             this.scheduleTask.cancel(true);
112             final WriteTransaction wTx = this.transactionChain.newWriteOnlyTransaction();
113             for (final KeyedInstanceIdentifier<Node, NodeKey> statId : this.statsMap.keySet()) {
114                 wTx.delete(LogicalDatastoreType.OPERATIONAL, statId);
115             }
116             wTx.commit().get();
117             this.statsMap.clear();
118             this.transactionChain.close();
119             this.scheduler.shutdown();
120         }
121     }
122
123     @Override
124     public synchronized void onTransactionChainFailed(final TransactionChain<?, ?> chain,
125             final AsyncTransaction<?, ?> transaction, final Throwable cause) {
126         LOG.error("Transaction chain {} failed for tx {}",
127                 chain, transaction != null ? transaction.getIdentifier() : null, cause);
128
129         if (!closed.get()) {
130             transactionChain.close();
131             transactionChain = dataBroker.createTransactionChain(this);
132         }
133     }
134
135     @Override
136     public synchronized void onTransactionChainSuccessful(final TransactionChain<?, ?> chain) {
137         LOG.debug("Transaction chain {} successful.", chain);
138     }
139
140     @Override
141     public synchronized void bind(final KeyedInstanceIdentifier<Node, NodeKey> nodeId,
142             final PcepSessionState sessionState) {
143         this.statsMap.put(nodeId, sessionState);
144     }
145
146     @Override
147     public synchronized void unbind(final KeyedInstanceIdentifier<Node, NodeKey> nodeId) {
148         this.statsMap.remove(nodeId);
149         final WriteTransaction wTx = this.transactionChain.newWriteOnlyTransaction();
150         wTx.delete(LogicalDatastoreType.OPERATIONAL, nodeId);
151         try {
152             wTx.commit().get();
153         } catch (final InterruptedException | ExecutionException e) {
154             LOG.warn("Failed to remove Pcep Node stats {}.", nodeId.getKey().getNodeId());
155         }
156     }
157 }