Switch to JDT annotations for Nullable and NonNull
[netvirt.git] / statistics / impl / src / main / java / org / opendaylight / netvirt / statistics / StatisticsImpl.java
1 /*
2  * Copyright (c) 2017 HPE, Inc. and others. 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 package org.opendaylight.netvirt.statistics;
9
10 import com.google.common.base.Optional;
11 import com.google.common.util.concurrent.CheckedFuture;
12 import com.google.common.util.concurrent.FutureCallback;
13 import com.google.common.util.concurrent.Futures;
14 import com.google.common.util.concurrent.ListenableFuture;
15 import com.google.common.util.concurrent.MoreExecutors;
16 import com.google.common.util.concurrent.SettableFuture;
17 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
18 import java.math.BigInteger;
19 import java.util.ArrayList;
20 import java.util.HashMap;
21 import java.util.HashSet;
22 import java.util.List;
23 import java.util.Map;
24 import java.util.Map.Entry;
25 import java.util.Set;
26 import java.util.UUID;
27 import java.util.concurrent.ExecutionException;
28 import java.util.concurrent.Future;
29 import org.eclipse.jdt.annotation.NonNull;
30 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
31 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
32 import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
33 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
34 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
35 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
36 import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
37 import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
38 import org.opendaylight.genius.interfacemanager.globals.InterfaceInfo;
39 import org.opendaylight.genius.interfacemanager.interfaces.IInterfaceManager;
40 import org.opendaylight.genius.mdsalutil.MDSALUtil;
41 import org.opendaylight.genius.mdsalutil.MatchInfoBase;
42 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
43 import org.opendaylight.infrautils.utils.concurrent.ListenableFutures;
44 import org.opendaylight.netvirt.statistics.api.ICountersInterfaceChangeHandler;
45 import org.opendaylight.netvirt.vpnmanager.api.InterfaceUtils;
46 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Match;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdInput;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdInputBuilder;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdOutput;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.CreateIdPoolInput;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.CreateIdPoolInputBuilder;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.CreateIdPoolOutput;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdPools;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.ReleaseIdInput;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.ReleaseIdInputBuilder;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.ReleaseIdOutput;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.id.pools.IdPool;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.id.pools.IdPoolKey;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.statistics.rev170120.AcquireElementCountersRequestHandlerInput;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.statistics.rev170120.AcquireElementCountersRequestHandlerOutput;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.statistics.rev170120.AcquireElementCountersRequestHandlerOutputBuilder;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.statistics.rev170120.CleanAllElementCounterRequestsInput;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.statistics.rev170120.CleanAllElementCounterRequestsOutput;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.statistics.rev170120.EgressElementCountersRequestConfig;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.statistics.rev170120.EgressElementCountersRequestConfigBuilder;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.statistics.rev170120.GetElementCountersByHandlerInput;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.statistics.rev170120.GetElementCountersByHandlerOutput;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.statistics.rev170120.GetElementCountersByHandlerOutputBuilder;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.statistics.rev170120.GetNodeAggregatedCountersInput;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.statistics.rev170120.GetNodeAggregatedCountersOutput;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.statistics.rev170120.GetNodeAggregatedCountersOutputBuilder;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.statistics.rev170120.GetNodeConnectorCountersInput;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.statistics.rev170120.GetNodeConnectorCountersOutput;
81 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.statistics.rev170120.GetNodeConnectorCountersOutputBuilder;
82 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.statistics.rev170120.GetNodeCountersInput;
83 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.statistics.rev170120.GetNodeCountersOutput;
84 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.statistics.rev170120.GetNodeCountersOutputBuilder;
85 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.statistics.rev170120.IngressElementCountersRequestConfig;
86 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.statistics.rev170120.IngressElementCountersRequestConfigBuilder;
87 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.statistics.rev170120.ReleaseElementCountersRequestHandlerInput;
88 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.statistics.rev170120.ReleaseElementCountersRequestHandlerOutput;
89 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.statistics.rev170120.StatisticsService;
90 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.statistics.rev170120.counterrequestsconfig.CounterRequests;
91 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.statistics.rev170120.counterrequestsconfig.CounterRequestsBuilder;
92 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.statistics.rev170120.counterrequestsconfig.CounterRequestsKey;
93 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.statistics.rev170120.elementrequestdata.Filters;
94 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.statistics.rev170120.elementrequestdata.filters.TcpFilter;
95 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.statistics.rev170120.elementrequestdata.filters.UdpFilter;
96 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.statistics.rev170120.result.CounterResult;
97 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.statistics.rev170120.result.CounterResultBuilder;
98 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.statistics.rev170120.result.counterresult.Groups;
99 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.statistics.rev170120.result.counterresult.GroupsBuilder;
100 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.statistics.rev170120.result.counterresult.groups.Counters;
101 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.statistics.rev170120.result.counterresult.groups.CountersBuilder;
102 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
103 import org.opendaylight.yangtools.yang.common.RpcError.ErrorType;
104 import org.opendaylight.yangtools.yang.common.RpcResult;
105 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
106 import org.slf4j.Logger;
107 import org.slf4j.LoggerFactory;
108
109 public class StatisticsImpl implements StatisticsService, ICountersInterfaceChangeHandler {
110     private static final Logger LOG = LoggerFactory.getLogger(StatisticsImpl.class);
111     private final DataBroker db;
112     private final ManagedNewTransactionRunner txRunner;
113     private final CounterRetriever counterRetriever;
114     private final IInterfaceManager interfaceManager;
115     private final IMdsalApiManager mdsalApiManager;
116     private final IdManagerService idManagerService;
117     private final StatisticsCounters statisticsCounters;
118
119     public StatisticsImpl(DataBroker db, CounterRetriever counterRetriever, IInterfaceManager interfaceManager,
120             IMdsalApiManager mdsalApiManager, IdManagerService idManagerService,
121             StatisticsCounters statisticsCounters) {
122         this.db = db;
123         this.txRunner = new ManagedNewTransactionRunnerImpl(db);
124         this.counterRetriever = counterRetriever;
125         this.interfaceManager = interfaceManager;
126         this.mdsalApiManager = mdsalApiManager;
127         this.idManagerService = idManagerService;
128         this.statisticsCounters = statisticsCounters;
129         initializeCountrsConfigDataSrore();
130     }
131
132     @Override
133     @SuppressWarnings("checkstyle:illegalCatch")
134     public ListenableFuture<RpcResult<GetNodeCountersOutput>> getNodeCounters(GetNodeCountersInput input) {
135         BigInteger dpId = input.getNodeId();
136         LOG.trace("getting node counters for node {}", dpId);
137         GetNodeCountersOutputBuilder gncob = new GetNodeCountersOutputBuilder();
138
139         List<CounterResult> counterResults = new ArrayList<>();
140         try {
141             if (!getNodeResult(counterResults, dpId)) {
142                 statisticsCounters.failedGettingNodeCounters();
143                 return RpcResultBuilder.<GetNodeCountersOutput>failed()
144                         .withError(ErrorType.APPLICATION, "failed to get node counters for node: " + dpId)
145                         .buildFuture();
146             }
147         } catch (RuntimeException e) {
148             LOG.warn("failed to get counter result for node {}", dpId, e);
149             return RpcResultBuilder.<GetNodeCountersOutput>failed()
150                     .withError(ErrorType.APPLICATION, "failed to get node counters for node: " + dpId).buildFuture();
151         }
152
153         gncob.setCounterResult(counterResults);
154         return RpcResultBuilder.success(gncob.build()).buildFuture();
155     }
156
157     @Override
158     @SuppressWarnings("checkstyle:illegalCatch")
159     public ListenableFuture<RpcResult<GetNodeAggregatedCountersOutput>> getNodeAggregatedCounters(
160             GetNodeAggregatedCountersInput input) {
161         BigInteger dpId = input.getNodeId();
162         LOG.trace("getting aggregated node counters for node {}", dpId);
163         GetNodeAggregatedCountersOutputBuilder gnacob = new GetNodeAggregatedCountersOutputBuilder();
164
165         List<CounterResult> aggregatedCounterResults = new ArrayList<>();
166         try {
167             if (!getNodeAggregatedResult(aggregatedCounterResults, dpId)) {
168                 statisticsCounters.failedGettingAggregatedNodeCounters();
169                 return RpcResultBuilder.<GetNodeAggregatedCountersOutput>failed()
170                         .withError(ErrorType.APPLICATION, "failed to get node aggregated counters for node " + dpId)
171                         .buildFuture();
172             }
173         } catch (Exception e) {
174             LOG.warn("failed to get counter result for node {}", dpId, e);
175             return RpcResultBuilder.<GetNodeAggregatedCountersOutput>failed()
176                     .withError(ErrorType.APPLICATION, "failed to get node aggregated counters for node " + dpId)
177                     .buildFuture();
178         }
179
180         gnacob.setCounterResult(aggregatedCounterResults);
181         return RpcResultBuilder.success(gnacob.build()).buildFuture();
182     }
183
184     @Override
185     @SuppressWarnings("checkstyle:illegalCatch")
186     public ListenableFuture<RpcResult<GetNodeConnectorCountersOutput>> getNodeConnectorCounters(
187             GetNodeConnectorCountersInput input) {
188         String portId = input.getPortId();
189         LOG.trace("getting port counters of port {}", portId);
190
191         Interface interfaceState = InterfaceUtils.getInterfaceStateFromOperDS(db, portId);
192         if (interfaceState == null) {
193             LOG.warn("trying to get counters for non exist port {}", portId);
194             return RpcResultBuilder.<GetNodeConnectorCountersOutput>failed().buildFuture();
195         }
196
197         BigInteger dpId = InterfaceUtils.getDpIdFromInterface(interfaceState);
198         if (interfaceState.getLowerLayerIf() == null || interfaceState.getLowerLayerIf().isEmpty()) {
199             LOG.warn("Lower layer if wasn't found for port {}", portId);
200             return RpcResultBuilder.<GetNodeConnectorCountersOutput>failed().buildFuture();
201         }
202
203         String portNumber = interfaceState.getLowerLayerIf().get(0);
204         portNumber = portNumber.split(":")[2];
205         List<CounterResult> counterResults = new ArrayList<>();
206
207         try {
208             if (!getNodeConnectorResult(counterResults, dpId, portNumber)) {
209                 statisticsCounters.failedGettingNodeConnectorCounters();
210                 return RpcResultBuilder.<GetNodeConnectorCountersOutput>failed()
211                         .withError(ErrorType.APPLICATION, "failed to get port counters").buildFuture();
212             }
213         } catch (RuntimeException e) {
214             LOG.warn("failed to get counter result for port {}", portId, e);
215         }
216
217         GetNodeConnectorCountersOutputBuilder gpcob = new GetNodeConnectorCountersOutputBuilder();
218         gpcob.setCounterResult(counterResults);
219         return RpcResultBuilder.success(gpcob.build()).buildFuture();
220     }
221
222     @Override
223     public ListenableFuture<RpcResult<AcquireElementCountersRequestHandlerOutput>> acquireElementCountersRequestHandler(
224             AcquireElementCountersRequestHandlerInput input) {
225         AcquireElementCountersRequestHandlerOutputBuilder aecrhob =
226                 new AcquireElementCountersRequestHandlerOutputBuilder();
227         UUID randomNumber = UUID.randomUUID();
228         Integer intRequestKey = allocateId(randomNumber.toString());
229         if (intRequestKey == null) {
230             LOG.warn("failed generating unique request identifier");
231             statisticsCounters.failedGeneratingUniqueRequestId();
232             return RpcResultBuilder.<AcquireElementCountersRequestHandlerOutput>failed()
233                     .withError(ErrorType.APPLICATION, "failed generating unique request identifier").buildFuture();
234         }
235         String requestKey = String.valueOf(intRequestKey);
236         SettableFuture<RpcResult<AcquireElementCountersRequestHandlerOutput>> result = SettableFuture.create();
237
238         ListenableFutures.addErrorLogging(
239             txRunner.callWithNewReadWriteTransactionAndSubmit(transaction -> {
240                 if (input.getIncomingTraffic() != null) {
241                     Optional<EgressElementCountersRequestConfig> eecrcOpt =
242                             transaction.read(LogicalDatastoreType.CONFIGURATION,
243                                     CountersServiceUtils.EECRC_IDENTIFIER).checkedGet();
244                     if (!eecrcOpt.isPresent()) {
245                         LOG.warn("failed creating incoming traffic counter request data container in DB");
246                         statisticsCounters.failedCreatingEgressCounterDataConfig();
247                         result.setFuture(RpcResultBuilder.<AcquireElementCountersRequestHandlerOutput>failed()
248                                 .withError(ErrorType.APPLICATION,
249                                         "failed creating egress counter request data container in DB")
250                                 .buildFuture());
251                         return;
252                     }
253                     if (!isIdenticalCounterRequestExist(input.getPortId(),
254                             ElementCountersDirection.EGRESS.toString(),
255                             input.getIncomingTraffic().getFilters(), eecrcOpt.get().getCounterRequests())) {
256                         installCounterSpecificRules(input.getPortId(), getLportTag(input.getPortId()),
257                                 getDpn(input.getPortId()), ElementCountersDirection.EGRESS,
258                                 input.getIncomingTraffic().getFilters());
259                     }
260                     putEgressElementCounterRequestInConfig(input, ElementCountersDirection.EGRESS, transaction,
261                             requestKey, CountersServiceUtils.EECRC_IDENTIFIER, eecrcOpt, randomNumber.toString());
262
263                     aecrhob.setIncomingTrafficHandler(requestKey);
264
265                     bindCountersServiceIfUnbound(input.getPortId(), ElementCountersDirection.EGRESS);
266                 }
267
268                 if (input.getOutgoingTraffic() != null) {
269                     Optional<IngressElementCountersRequestConfig> iecrcOpt =
270                             transaction.read(LogicalDatastoreType.CONFIGURATION,
271                                     CountersServiceUtils.IECRC_IDENTIFIER).checkedGet();
272                     if (!iecrcOpt.isPresent()) {
273                         LOG.warn("failed creating outgoing traffc counter request data container in DB");
274                         statisticsCounters.failedCreatingIngressCounterDataConfig();
275                         result.setFuture(RpcResultBuilder.<AcquireElementCountersRequestHandlerOutput>failed()
276                                 .withError(ErrorType.APPLICATION,
277                                         "failed creating ingress counter request data container in DB")
278                                 .buildFuture());
279                         return;
280                     }
281                     if (!isIdenticalCounterRequestExist(input.getPortId(),
282                             ElementCountersDirection.INGRESS.toString(),
283                             input.getOutgoingTraffic().getFilters(), iecrcOpt.get().getCounterRequests())) {
284                         installCounterSpecificRules(input.getPortId(), getLportTag(input.getPortId()),
285                                 getDpn(input.getPortId()), ElementCountersDirection.INGRESS,
286                                 input.getOutgoingTraffic().getFilters());
287                     }
288                     putIngressElementCounterRequestInConfig(input, ElementCountersDirection.INGRESS, transaction,
289                             requestKey, CountersServiceUtils.IECRC_IDENTIFIER, iecrcOpt, randomNumber.toString());
290
291                     aecrhob.setIncomingTrafficHandler(requestKey);
292
293                     bindCountersServiceIfUnbound(input.getPortId(), ElementCountersDirection.INGRESS);
294
295                     result.setFuture(RpcResultBuilder.success(aecrhob.build()).buildFuture());
296                 }
297             }), LOG, "Error acquiring element counters");
298
299         return result;
300     }
301
302     @Override
303     public ListenableFuture<RpcResult<ReleaseElementCountersRequestHandlerOutput>> releaseElementCountersRequestHandler(
304             ReleaseElementCountersRequestHandlerInput input) {
305         InstanceIdentifier<CounterRequests> ingressPath =
306                 InstanceIdentifier.builder(IngressElementCountersRequestConfig.class)
307                         .child(CounterRequests.class, new CounterRequestsKey(input.getHandler())).build();
308         InstanceIdentifier<CounterRequests> egressPath =
309                 InstanceIdentifier.builder(EgressElementCountersRequestConfig.class)
310                         .child(CounterRequests.class, new CounterRequestsKey(input.getHandler())).build();
311
312         SettableFuture<RpcResult<ReleaseElementCountersRequestHandlerOutput>> result = SettableFuture.create();
313         ListenableFutures.addErrorLogging(txRunner.callWithNewReadWriteTransactionAndSubmit(tx -> {
314             Optional<IngressElementCountersRequestConfig> iecrcOpt =
315                     tx.read(LogicalDatastoreType.CONFIGURATION, CountersServiceUtils.IECRC_IDENTIFIER).checkedGet();
316             Optional<EgressElementCountersRequestConfig> eecrcOpt =
317                     tx.read(LogicalDatastoreType.CONFIGURATION, CountersServiceUtils.EECRC_IDENTIFIER).checkedGet();
318             if (!iecrcOpt.isPresent() || !eecrcOpt.isPresent()) {
319                 LOG.warn("Couldn't read element counters config data from DB");
320                 statisticsCounters.failedReadingCounterDataFromConfig();
321                 result.setFuture(RpcResultBuilder.<ReleaseElementCountersRequestHandlerOutput>failed()
322                         .withError(ErrorType.APPLICATION, "Couldn't read element counters config data from DB")
323                         .buildFuture());
324                 return;
325             }
326             Optional<CounterRequests> ingressRequestOpt =
327                     tx.read(LogicalDatastoreType.CONFIGURATION, ingressPath).checkedGet();
328             Optional<CounterRequests> egressRequestOpt =
329                     tx.read(LogicalDatastoreType.CONFIGURATION, egressPath).checkedGet();
330             if (!ingressRequestOpt.isPresent() && !egressRequestOpt.isPresent()) {
331                 LOG.warn("Handler does not exists");
332                 statisticsCounters.unknownRequestHandler();
333                 result.setFuture(RpcResultBuilder.<ReleaseElementCountersRequestHandlerOutput>failed()
334                         .withError(ErrorType.APPLICATION, "Handler does not exists").buildFuture());
335                 return;
336             }
337             String generatedKey = null;
338             if (ingressRequestOpt.isPresent()) {
339                 handleReleaseTransaction(tx, input, ingressPath, ingressRequestOpt,
340                         iecrcOpt.get().getCounterRequests());
341                 generatedKey = ingressRequestOpt.get().getGeneratedUniqueId();
342             }
343             if (egressRequestOpt.isPresent()) {
344                 handleReleaseTransaction(tx, input, egressPath, egressRequestOpt, eecrcOpt.get().getCounterRequests());
345                 generatedKey = egressRequestOpt.get().getGeneratedUniqueId();
346             }
347             releaseId(generatedKey);
348             result.setFuture(RpcResultBuilder.<ReleaseElementCountersRequestHandlerOutput>success().buildFuture());
349         }), LOG, "Error releasing element counters");
350
351         return result;
352     }
353
354     @Override
355     public ListenableFuture<RpcResult<GetElementCountersByHandlerOutput>> getElementCountersByHandler(
356             GetElementCountersByHandlerInput input) {
357         InstanceIdentifier<CounterRequests> ingressPath =
358                 InstanceIdentifier.builder(IngressElementCountersRequestConfig.class)
359                         .child(CounterRequests.class, new CounterRequestsKey(input.getHandler())).build();
360         InstanceIdentifier<CounterRequests> egressPath =
361                 InstanceIdentifier.builder(EgressElementCountersRequestConfig.class)
362                         .child(CounterRequests.class, new CounterRequestsKey(input.getHandler())).build();
363
364         ReadOnlyTransaction tx = db.newReadOnlyTransaction();
365         CheckedFuture<Optional<CounterRequests>, ReadFailedException> ingressRequestData =
366                 tx.read(LogicalDatastoreType.CONFIGURATION, ingressPath);
367         CheckedFuture<Optional<CounterRequests>, ReadFailedException> egressRequestData =
368                 tx.read(LogicalDatastoreType.CONFIGURATION, egressPath);
369         List<CounterResult> counters = new ArrayList<>();
370
371         try {
372             if (!ingressRequestData.get().isPresent() && !egressRequestData.get().isPresent()) {
373                 LOG.warn("Handler does not exists");
374                 return RpcResultBuilder.<GetElementCountersByHandlerOutput>failed()
375                         .withError(ErrorType.APPLICATION, "Handler does not exists").buildFuture();
376             }
377             if (ingressRequestData.get().isPresent()) {
378                 CounterRequests ingressCounterRequest = ingressRequestData.get().get();
379                 CounterResultDataStructure ingressCounterResultDS = createElementCountersResult(ingressCounterRequest);
380                 if (ingressCounterResultDS == null) {
381                     LOG.warn("Unable to get counter results");
382                     statisticsCounters.failedGettingCounterResults();
383                     return RpcResultBuilder.<GetElementCountersByHandlerOutput>failed()
384                             .withError(ErrorType.APPLICATION, "Unable to get counter results").buildFuture();
385                 }
386                 createCounterResults(counters, ingressCounterResultDS, CountersServiceUtils.INGRESS_COUNTER_RESULT_ID);
387             }
388             if (egressRequestData.get().isPresent()) {
389                 CounterRequests egressCounterRequest = egressRequestData.get().get();
390                 CounterResultDataStructure egressCounterResultDS = createElementCountersResult(egressCounterRequest);
391                 if (egressCounterResultDS == null) {
392                     LOG.warn("Unable to get counter results");
393                     statisticsCounters.failedGettingCounterResults();
394                     return RpcResultBuilder.<GetElementCountersByHandlerOutput>failed()
395                             .withError(ErrorType.APPLICATION, "Unable to get counter results").buildFuture();
396                 }
397                 createCounterResults(counters, egressCounterResultDS, CountersServiceUtils.EGRESS_COUNTER_RESULT_ID);
398             }
399         } catch (InterruptedException | ExecutionException e) {
400             LOG.warn("failed to get counter request data from DB");
401             return RpcResultBuilder.<GetElementCountersByHandlerOutput>failed()
402                     .withError(ErrorType.APPLICATION, "failed to get counter request data from DB").buildFuture();
403         }
404
405         GetElementCountersByHandlerOutputBuilder gecbhob = new GetElementCountersByHandlerOutputBuilder();
406         gecbhob.setCounterResult(counters);
407         return RpcResultBuilder.success(gecbhob.build()).buildFuture();
408     }
409
410     @Override
411     public void handleInterfaceRemoval(String interfaceId) {
412         CheckedFuture<Optional<IngressElementCountersRequestConfig>, ReadFailedException> iecrc;
413         CheckedFuture<Optional<EgressElementCountersRequestConfig>, ReadFailedException> eecrc;
414         try (ReadOnlyTransaction tx = db.newReadOnlyTransaction()) {
415             iecrc = tx.read(LogicalDatastoreType.CONFIGURATION, CountersServiceUtils.IECRC_IDENTIFIER);
416             eecrc = tx.read(LogicalDatastoreType.CONFIGURATION, CountersServiceUtils.EECRC_IDENTIFIER);
417         }
418
419         try {
420             Optional<IngressElementCountersRequestConfig> iecrcOpt = iecrc.get();
421             Optional<EgressElementCountersRequestConfig> eecrcOpt = eecrc.get();
422             if (!iecrcOpt.isPresent() || !eecrcOpt.isPresent()) {
423                 LOG.warn("Couldn't read element counters config data from DB");
424                 statisticsCounters.failedReadingCounterDataFromConfig();
425                 return;
426             }
427             removeAllElementCounterRequestsOnPort(interfaceId, iecrcOpt.get().getCounterRequests());
428             removeAllElementCounterRequestsOnPort(interfaceId, eecrcOpt.get().getCounterRequests());
429         } catch (InterruptedException | ExecutionException e) {
430             LOG.warn("failed to get counter request data from DB");
431             statisticsCounters.failedGettingCounterResultsPortRemoval();
432             return;
433         }
434     }
435
436     @Override
437     public ListenableFuture<RpcResult<CleanAllElementCounterRequestsOutput>> cleanAllElementCounterRequests(
438             CleanAllElementCounterRequestsInput input) {
439         ReadOnlyTransaction tx = db.newReadOnlyTransaction();
440         CheckedFuture<Optional<IngressElementCountersRequestConfig>, ReadFailedException> iecrc =
441                 tx.read(LogicalDatastoreType.CONFIGURATION, CountersServiceUtils.IECRC_IDENTIFIER);
442         CheckedFuture<Optional<EgressElementCountersRequestConfig>, ReadFailedException> eecrc =
443                 tx.read(LogicalDatastoreType.CONFIGURATION, CountersServiceUtils.EECRC_IDENTIFIER);
444         try {
445             Optional<IngressElementCountersRequestConfig> iecrcOpt = iecrc.get();
446             Optional<EgressElementCountersRequestConfig> eecrcOpt = eecrc.get();
447             if (!iecrcOpt.isPresent() || !eecrcOpt.isPresent()) {
448                 LOG.warn("Couldn't read element counters config data from DB");
449                 statisticsCounters.failedReadingCounterDataFromConfig();
450                 return RpcResultBuilder.<CleanAllElementCounterRequestsOutput>failed()
451                         .withError(ErrorType.APPLICATION, "Couldn't read element counters config data from DB")
452                         .buildFuture();
453             }
454             Set<String> idsToRelease = new HashSet<>();
455             if (input.getPortId() != null && !input.getPortId().isEmpty()) {
456                 idsToRelease
457                         .addAll(getAllPortRequestsUniqueIds(input.getPortId(), iecrcOpt.get().getCounterRequests()));
458                 idsToRelease
459                         .addAll(getAllPortRequestsUniqueIds(input.getPortId(), eecrcOpt.get().getCounterRequests()));
460                 removeAllElementCounterRequestsOnPort(input.getPortId(), iecrcOpt.get().getCounterRequests());
461                 removeAllElementCounterRequestsOnPort(input.getPortId(), eecrcOpt.get().getCounterRequests());
462             } else {
463                 idsToRelease.addAll(getAllRquestsUniqueIds(iecrcOpt.get().getCounterRequests()));
464                 idsToRelease.addAll(getAllRquestsUniqueIds(eecrcOpt.get().getCounterRequests()));
465                 removeAllElementCounterRequests(iecrcOpt.get().getCounterRequests());
466                 removeAllElementCounterRequests(eecrcOpt.get().getCounterRequests());
467             }
468             releaseIds(idsToRelease);
469         } catch (InterruptedException | ExecutionException e) {
470             LOG.warn("failed to get counter request data from DB");
471             return RpcResultBuilder.<CleanAllElementCounterRequestsOutput>failed()
472                     .withError(ErrorType.APPLICATION, "failed to get counter request data from DB").buildFuture();
473
474         }
475         return RpcResultBuilder.<CleanAllElementCounterRequestsOutput>success().buildFuture();
476     }
477
478     private Set<String> getAllPortRequestsUniqueIds(String interfaceId, List<CounterRequests> counterRequests) {
479         Set<String> result = new HashSet<>();
480         for (CounterRequests counterRequest : counterRequests) {
481             if (counterRequest.getPortId().equals(interfaceId)) {
482                 result.add(counterRequest.getGeneratedUniqueId());
483             }
484         }
485         return result;
486     }
487
488     private Set<String> getAllRquestsUniqueIds(List<CounterRequests> counterRequests) {
489         Set<String> result = new HashSet<>();
490         for (CounterRequests counterRequest : counterRequests) {
491             result.add(counterRequest.getGeneratedUniqueId());
492         }
493         return result;
494     }
495
496     private void releaseIds(Set<String> ids) {
497         for (String id : ids) {
498             releaseId(id);
499         }
500     }
501
502     private void removeAllElementCounterRequestsOnPort(String interfaceId, List<CounterRequests> counterRequests) {
503         unbindCountersServiceIfBound(interfaceId, ElementCountersDirection.INGRESS);
504         unbindCountersServiceIfBound(interfaceId, ElementCountersDirection.EGRESS);
505         if (counterRequests != null) {
506             for (CounterRequests counterRequest : counterRequests) {
507                 if (interfaceId.equals(counterRequest.getPortId())) {
508                     countersRequestCleanup(counterRequest);
509                 }
510             }
511         }
512     }
513
514     private void removeAllElementCounterRequests(List<CounterRequests> counterRequests) {
515         for (CounterRequests counterRequest : counterRequests) {
516             unbindCountersServiceIfBound(counterRequest.getPortId(), ElementCountersDirection.INGRESS);
517             unbindCountersServiceIfBound(counterRequest.getPortId(), ElementCountersDirection.EGRESS);
518             countersRequestCleanup(counterRequest);
519         }
520     }
521
522     private void countersRequestCleanup(CounterRequests counterRequest) {
523         ElementCountersDirection direction = ElementCountersDirection.valueOf(counterRequest.getTrafficDirection());
524         deleteCounterSpecificRules(counterRequest.getPortId(), counterRequest.getLportTag(), counterRequest.getDpn(),
525                 direction, counterRequest.getFilters());
526         deleteCounterRequest(counterRequest, direction);
527     }
528
529     private void deleteCounterSpecificRules(String portId, int lportTag, BigInteger dpn,
530             ElementCountersDirection direction, Filters filters) {
531         List<ElementCountersRequest> ecrList = createElementCounterRequest(portId, lportTag, dpn, direction, filters);
532         for (ElementCountersRequest ecr : ecrList) {
533             if (ElementCountersDirection.INGRESS.equals(ecr.getDirection())) {
534                 IngressCountersServiceImpl icsi = new IngressCountersServiceImpl(db, interfaceManager, mdsalApiManager);
535                 icsi.deleteCounterRules(ecr);
536             } else if (ElementCountersDirection.EGRESS.equals(ecr.getDirection())) {
537                 EgressCountersServiceImpl ecsi = new EgressCountersServiceImpl(db, interfaceManager, mdsalApiManager);
538                 ecsi.deleteCounterRules(ecr);
539             }
540         }
541     }
542
543     private void deleteCounterRequest(CounterRequests counterRequest, ElementCountersDirection direction) {
544         ListenableFutures.addErrorLogging(
545             txRunner.callWithNewWriteOnlyTransactionAndSubmit(tx -> {
546                 if (ElementCountersDirection.INGRESS.equals(direction)) {
547                     tx.delete(LogicalDatastoreType.CONFIGURATION, InstanceIdentifier
548                             .builder(IngressElementCountersRequestConfig.class)
549                             .child(CounterRequests.class,
550                                     new CounterRequestsKey(counterRequest.key().getRequestId()))
551                             .build());
552                 } else if (ElementCountersDirection.EGRESS.equals(direction)) {
553                     tx.delete(LogicalDatastoreType.CONFIGURATION, InstanceIdentifier
554                             .builder(EgressElementCountersRequestConfig.class)
555                             .child(CounterRequests.class,
556                                     new CounterRequestsKey(counterRequest.key().getRequestId()))
557                             .build());
558                 }
559             }), LOG, "Error deleting counter");
560     }
561
562     private CounterResultDataStructure createElementCountersResult(CounterRequests counterRequest) {
563         ElementCountersRequest ecr =
564                 createElementCounterRequest(counterRequest.getPortId(), counterRequest.getLportTag(),
565                         counterRequest.getDpn(), ElementCountersDirection.valueOf(counterRequest.getTrafficDirection()),
566                         counterRequest.getFilters()).iterator().next();
567         BigInteger dpId = getDpn(ecr.getPortId());
568         InterfaceInfo interfaceInfo = interfaceManager.getInterfaceInfo(ecr.getPortId());
569         if (interfaceInfo == null) {
570             return null;
571         }
572         int lportTag = interfaceInfo.getInterfaceTag();
573         List<MatchInfoBase> matches = CountersServiceUtils.getCounterFlowMatch(ecr, lportTag,
574                 ElementCountersDirection.valueOf(counterRequest.getTrafficDirection()));
575         Match match = MDSALUtil.buildMatches(matches);
576         return counterRetriever.getSwitchFlowCountersDirect(dpId, match);
577     }
578
579     private void initializeCountrsConfigDataSrore() {
580         ListenableFutures.addErrorLogging(
581             txRunner.callWithNewReadWriteTransactionAndSubmit(transaction -> {
582                 Optional<IngressElementCountersRequestConfig> iecrcOpt =
583                         transaction.read(LogicalDatastoreType.CONFIGURATION,
584                                 CountersServiceUtils.IECRC_IDENTIFIER).checkedGet();
585                 Optional<EgressElementCountersRequestConfig> eecrcOpt =
586                         transaction.read(LogicalDatastoreType.CONFIGURATION,
587                                 CountersServiceUtils.EECRC_IDENTIFIER).checkedGet();
588                 if (!iecrcOpt.isPresent()) {
589                     creatIngressEelementCountersContainerInConfig(transaction,
590                             CountersServiceUtils.IECRC_IDENTIFIER);
591                 }
592                 if (!eecrcOpt.isPresent()) {
593                     creatEgressEelementCountersContainerInConfig(transaction,
594                             CountersServiceUtils.EECRC_IDENTIFIER);
595                 }
596             }), LOG, "Failed to create counters in config datastore");
597     }
598
599     private void handleReleaseTransaction(WriteTransaction transaction, ReleaseElementCountersRequestHandlerInput input,
600             InstanceIdentifier<CounterRequests> path, Optional<CounterRequests> requestData,
601             List<CounterRequests> counterRequests) {
602         transaction.delete(LogicalDatastoreType.CONFIGURATION, path);
603         CounterRequests counterRequest = requestData.get();
604         if (shouldUnbindCountersService(counterRequest.getPortId(), counterRequest.key().getRequestId(),
605                 counterRequests)) {
606             unbindCountersServiceIfBound(counterRequest.getPortId(),
607                     ElementCountersDirection.valueOf(counterRequest.getTrafficDirection()));
608         }
609         if (!isIdenticalCounterRequestExist(input.getHandler(), counterRequest.getPortId(),
610                 counterRequest.getTrafficDirection(), counterRequest.getFilters(), counterRequests)) {
611             deleteCounterSpecificRules(counterRequest.getPortId(), counterRequest.getLportTag(),
612                     counterRequest.getDpn(), ElementCountersDirection.valueOf(counterRequest.getTrafficDirection()),
613                     counterRequest.getFilters());
614         }
615     }
616
617     private boolean getNodeConnectorResult(List<CounterResult> counters, BigInteger dpId, String portNumber) {
618         CounterResultDataStructure counterResultDS =
619                 counterRetriever.getNodeConnectorCountersDirect(new NodeId(CountersUtils.getNodeId(dpId)),
620                         new NodeConnectorId(CountersUtils.getNodeConnectorId(dpId, portNumber)));
621         if (counterResultDS == null) {
622             return false;
623         }
624
625         CounterResultBuilder crb = new CounterResultBuilder();
626         String resultId = CountersUtils.getNodeConnectorId(dpId, portNumber);
627         crb.setId(resultId);
628
629         createGroups(counters, counterResultDS, crb, resultId);
630
631         return !counters.isEmpty();
632     }
633
634     private boolean getNodeResult(List<CounterResult> counters, BigInteger dpId) {
635         InstanceIdentifier<Node> nodeInstanceIdentifier = InstanceIdentifier.builder(Nodes.class)
636                 .child(Node.class, new NodeKey(new NodeId(CountersUtils.getNodeId(dpId)))).build();
637         Optional<Node> nodeOptional = MDSALUtil.read(db, LogicalDatastoreType.OPERATIONAL, nodeInstanceIdentifier);
638         if (!nodeOptional.isPresent()) {
639             return false;
640         }
641
642         Node node = nodeOptional.get();
643         CounterResultDataStructure counterResultDS = counterRetriever.getNodeCountersDirect(node);
644         if (counterResultDS == null) {
645             return false;
646         }
647
648         createCounterResults(counters, counterResultDS);
649
650         return !counters.isEmpty();
651     }
652
653     private boolean getNodeAggregatedResult(List<CounterResult> aggregatedCounters, BigInteger dpId) {
654         InstanceIdentifier<Node> nodeInstanceIdentifier = InstanceIdentifier.builder(Nodes.class)
655                 .child(Node.class, new NodeKey(new NodeId(CountersUtils.getNodeId(dpId)))).build();
656         Optional<Node> nodeOptional = MDSALUtil.read(db, LogicalDatastoreType.OPERATIONAL, nodeInstanceIdentifier);
657         if (!nodeOptional.isPresent()) {
658             return false;
659         }
660
661         Node node = nodeOptional.get();
662         CounterResultDataStructure counters = counterRetriever.getNodeCountersDirect(node);
663         if (counters == null || counters.isEmpty()) {
664             return false;
665         }
666
667         CounterResultDataStructure aggregatedResultsDS =
668                 CountersUtils.aggregateCounters(counters, CountersUtils.getNodeId(dpId));
669         createCounterResults(aggregatedCounters, aggregatedResultsDS);
670         return !aggregatedCounters.isEmpty();
671
672     }
673
674     private void createCounterResults(List<CounterResult> counters, CounterResultDataStructure counterResultDS) {
675         for (String counterResultId : counterResultDS.getResults().keySet()) {
676             CounterResultBuilder crb = new CounterResultBuilder();
677             crb.setId(counterResultId);
678             createGroups(counters, counterResultDS, crb, counterResultId);
679         }
680     }
681
682     private void createCounterResults(List<CounterResult> counters, CounterResultDataStructure counterResultDS,
683             String resultId) {
684         for (String counterResultId : counterResultDS.getResults().keySet()) {
685             CounterResultBuilder crb = new CounterResultBuilder();
686             crb.setId(resultId);
687             createGroups(counters, counterResultDS, crb, counterResultId);
688         }
689     }
690
691     private void createGroups(List<CounterResult> counters, CounterResultDataStructure counterResultDS,
692             CounterResultBuilder crb, String resultId) {
693         List<Groups> groups = new ArrayList<>();
694         Map<String, Map<String, BigInteger>> counterGroups = counterResultDS.getGroups(resultId);
695         if (counterGroups != null && !counterGroups.isEmpty()) {
696             for (Entry<String, Map<String, BigInteger>> entry : counterGroups.entrySet()) {
697                 String groupName = entry.getKey();
698                 groups.add(createGroupsResult(groupName, entry.getValue()));
699             }
700             crb.setGroups(groups);
701             counters.add(crb.build());
702         }
703     }
704
705     private Groups createGroupsResult(String groupName, Map<String, BigInteger> countersMap) {
706         GroupsBuilder gb = new GroupsBuilder();
707         gb.setName(groupName);
708
709         Map<String, Counters> counters = new HashMap<>();
710         List<Counters> countersList = new ArrayList<>();
711         for (String counterName : countersMap.keySet()) {
712             addCountersToMap(countersMap, counters, counterName);
713         }
714         for (Counters counter : counters.values()) {
715             countersList.add(counter);
716         }
717
718         gb.setCounters(countersList);
719         return gb.build();
720     }
721
722     private Counters buildCounter(String counterName, BigInteger value, Counters prevCounter) {
723         BigInteger prevValue = BigInteger.ZERO;
724         if (prevCounter != null) {
725             prevValue = prevCounter.getValue();
726         }
727         CountersBuilder cb = new CountersBuilder();
728         cb.setName(counterName);
729         cb.setValue(value.add(prevValue));
730         return cb.build();
731     }
732
733     private void addCountersToMap(Map<String, BigInteger> result, Map<String, Counters> counters, String counterName) {
734         counters.put(counterName, buildCounter(counterName, result.get(counterName), counters.get(counterName)));
735     }
736
737     private void addElementCounterRequest(List<ElementCountersRequest> ecrList, String portId, int lportTag,
738             BigInteger dpn, ElementCountersDirection direction, Filters filters) {
739         ElementCountersRequest ecr = new ElementCountersRequest(portId);
740         ecr.setLportTag(lportTag);
741         ecr.setDpn(dpn);
742         ecr.setElementCountersDirection(direction);
743         if (filters.getIpFilter() != null) {
744             String ip = filters.getIpFilter().getIp();
745             if (ip != null) {
746                 ecr.addFilterToFilterGroup(CountersUtils.ELEMENT_COUNTERS_IP_FILTER_GROUP_NAME,
747                         CountersUtils.IP_FILTER_NAME, ip);
748             }
749         }
750
751         boolean isTcpPortExist = false;
752         if (filters.getTcpFilter() != null && filters.getTcpFilter().isOn()) {
753             TcpFilter tcpFilter = filters.getTcpFilter();
754             int srcPort = tcpFilter.getSrcPort();
755             int dstPort = tcpFilter.getDstPort();
756             if (srcPort != -1) {
757                 isTcpPortExist = true;
758                 ecr.addFilterToFilterGroup(CountersUtils.ELEMENT_COUNTERS_TCP_FILTER_GROUP_NAME,
759                         CountersUtils.TCP_SRC_PORT_FILTER_NAME, String.valueOf(srcPort));
760             }
761             if (dstPort != -1) {
762                 isTcpPortExist = true;
763                 ecr.addFilterToFilterGroup(CountersUtils.ELEMENT_COUNTERS_TCP_FILTER_GROUP_NAME,
764                         CountersUtils.TCP_DST_PORT_FILTER_NAME, String.valueOf(dstPort));
765             }
766             if (!isTcpPortExist) {
767                 ecr.addFilterToFilterGroup(CountersUtils.ELEMENT_COUNTERS_TCP_FILTER_GROUP_NAME,
768                         CountersUtils.TCP_FILTER_NAME, "");
769             }
770
771         } else if (filters.getUdpFilter() != null && filters.getUdpFilter().isOn()) {
772             UdpFilter udpFilter = filters.getUdpFilter();
773             int srcPort = udpFilter.getSrcPort();
774             int dstPort = udpFilter.getDstPort();
775             if (srcPort != -1) {
776                 isTcpPortExist = true;
777                 ecr.addFilterToFilterGroup(CountersUtils.ELEMENT_COUNTERS_UDP_FILTER_GROUP_NAME,
778                         CountersUtils.UDP_SRC_PORT_FILTER_NAME, String.valueOf(srcPort));
779             }
780             if (dstPort != -1) {
781                 isTcpPortExist = true;
782                 ecr.addFilterToFilterGroup(CountersUtils.ELEMENT_COUNTERS_UDP_FILTER_GROUP_NAME,
783                         CountersUtils.UDP_DST_PORT_FILTER_NAME, String.valueOf(dstPort));
784             }
785             if (!isTcpPortExist) {
786                 ecr.addFilterToFilterGroup(CountersUtils.ELEMENT_COUNTERS_UDP_FILTER_GROUP_NAME,
787                         CountersUtils.UDP_FILTER_NAME, "");
788             }
789         }
790
791         if (!ecr.getFilters().isEmpty()) {
792             ecrList.add(ecr);
793         }
794     }
795
796     @SuppressFBWarnings("SLF4J_FORMAT_SHOULD_BE_CONST")
797     private void logElementCounterRequests(List<ElementCountersRequest> ecrList) {
798         for (ElementCountersRequest counterRequest : ecrList) {
799             LOG.debug(counterRequest.toString());
800         }
801     }
802
803     private void bindCountersServiceIfUnbound(String interfaceId, ElementCountersDirection direction) {
804         if (ElementCountersDirection.INGRESS.equals(direction) && !interfaceManager.isServiceBoundOnInterfaceForIngress(
805                 CountersServiceUtils.INGRESS_COUNTERS_SERVICE_INDEX, interfaceId)) {
806             IngressCountersServiceImpl icsi = new IngressCountersServiceImpl(db, interfaceManager, mdsalApiManager);
807             icsi.bindService(interfaceId);
808             statisticsCounters.ingressCountersServiceBind();
809         } else if (ElementCountersDirection.EGRESS.equals(direction) && !interfaceManager
810                 .isServiceBoundOnInterfaceForEgress(CountersServiceUtils.EGRESS_COUNTERS_SERVICE_INDEX, interfaceId)) {
811             EgressCountersServiceImpl ecsi = new EgressCountersServiceImpl(db, interfaceManager, mdsalApiManager);
812             ecsi.bindService(interfaceId);
813             statisticsCounters.egressCountersServiceBind();
814         }
815     }
816
817     private void unbindCountersServiceIfBound(String interfaceId, ElementCountersDirection direction) {
818         if (ElementCountersDirection.INGRESS.equals(direction) && interfaceManager.isServiceBoundOnInterfaceForIngress(
819                 CountersServiceUtils.INGRESS_COUNTERS_SERVICE_INDEX, interfaceId)) {
820             IngressCountersServiceImpl icsi = new IngressCountersServiceImpl(db, interfaceManager, mdsalApiManager);
821             icsi.unBindService(interfaceId);
822             statisticsCounters.ingressCountersServiceUnbind();
823         } else if (ElementCountersDirection.EGRESS.equals(direction) && interfaceManager
824                 .isServiceBoundOnInterfaceForEgress(CountersServiceUtils.EGRESS_COUNTERS_SERVICE_INDEX, interfaceId)) {
825             EgressCountersServiceImpl ecsi = new EgressCountersServiceImpl(db, interfaceManager, mdsalApiManager);
826             ecsi.unBindService(interfaceId);
827             statisticsCounters.egressCountersServiceUnbind();
828         }
829     }
830
831     private boolean shouldUnbindCountersService(String portId, String requesId, List<CounterRequests> counterRequests) {
832         for (CounterRequests counterRequest : counterRequests) {
833             if (portId.equals(counterRequest.getPortId()) && !requesId.equals(counterRequest.key().getRequestId())) {
834                 return false;
835             }
836         }
837         return true;
838     }
839
840     private void installCounterSpecificRules(String portId, int lportTag, BigInteger dpn,
841             ElementCountersDirection direction, Filters filters) {
842         List<ElementCountersRequest> ecrList = createElementCounterRequest(portId, lportTag, dpn, direction, filters);
843         for (ElementCountersRequest ecr : ecrList) {
844             if (ElementCountersDirection.INGRESS.equals(ecr.getDirection())) {
845                 IngressCountersServiceImpl icsi = new IngressCountersServiceImpl(db, interfaceManager, mdsalApiManager);
846                 icsi.installCounterRules(ecr);
847             } else if (ElementCountersDirection.EGRESS.equals(ecr.getDirection())) {
848                 EgressCountersServiceImpl ecsi = new EgressCountersServiceImpl(db, interfaceManager, mdsalApiManager);
849                 ecsi.installCounterRules(ecr);
850             }
851         }
852     }
853
854     private boolean areFiltersEqual(Filters filterGroup1, Filters filterGroup2) {
855         if (filterGroup1 == null && filterGroup2 == null) {
856             return true;
857         }
858         if (filterGroup1 == null || filterGroup2 == null) {
859             return false;
860         }
861
862         return filterGroup1.toString().equals(filterGroup2.toString());
863     }
864
865     private void putIngressElementCounterRequestInConfig(AcquireElementCountersRequestHandlerInput input,
866             ElementCountersDirection direcion, ReadWriteTransaction transaction, String requestKey,
867             InstanceIdentifier<IngressElementCountersRequestConfig> ecrcIdentifier,
868             Optional<IngressElementCountersRequestConfig> iecrcOpt, String generatedUniqueId) {
869         IngressElementCountersRequestConfig requestConfig = iecrcOpt.get();
870         CounterRequestsBuilder crb = new CounterRequestsBuilder();
871         crb.setRequestId(requestKey);
872         crb.withKey(new CounterRequestsKey(requestKey));
873         crb.setFilters(input.getOutgoingTraffic().getFilters());
874         crb.setPortId(input.getPortId());
875         crb.setLportTag(getLportTag(input.getPortId()));
876         crb.setDpn(getDpn(input.getPortId()));
877         crb.setTrafficDirection(direcion.toString());
878         crb.setGeneratedUniqueId(generatedUniqueId);
879         List<CounterRequests> counterRequests = requestConfig.getCounterRequests();
880         counterRequests.add(crb.build());
881
882         IngressElementCountersRequestConfigBuilder ecrcb = new IngressElementCountersRequestConfigBuilder();
883         ecrcb.setCounterRequests(counterRequests);
884         requestConfig = ecrcb.build();
885         transaction.put(LogicalDatastoreType.CONFIGURATION, ecrcIdentifier, requestConfig,
886                 WriteTransaction.CREATE_MISSING_PARENTS);
887     }
888
889     private void putEgressElementCounterRequestInConfig(AcquireElementCountersRequestHandlerInput input,
890             ElementCountersDirection direcion, ReadWriteTransaction transaction, String requestKey,
891             InstanceIdentifier<EgressElementCountersRequestConfig> ecrcIdentifier,
892             Optional<EgressElementCountersRequestConfig> eecrcOpt, String generatedUniqueId) {
893         EgressElementCountersRequestConfig requestConfig = eecrcOpt.get();
894         CounterRequestsBuilder crb = new CounterRequestsBuilder();
895         crb.setRequestId(requestKey);
896         crb.withKey(new CounterRequestsKey(requestKey));
897         crb.setFilters(input.getIncomingTraffic().getFilters());
898         crb.setPortId(input.getPortId());
899         crb.setLportTag(getLportTag(input.getPortId()));
900         crb.setDpn(getDpn(input.getPortId()));
901         crb.setTrafficDirection(direcion.toString());
902         crb.setGeneratedUniqueId(generatedUniqueId);
903         List<CounterRequests> counterRequests = requestConfig.getCounterRequests();
904         counterRequests.add(crb.build());
905
906         EgressElementCountersRequestConfigBuilder ecrcb = new EgressElementCountersRequestConfigBuilder();
907         ecrcb.setCounterRequests(counterRequests);
908         requestConfig = ecrcb.build();
909         transaction.put(LogicalDatastoreType.CONFIGURATION, ecrcIdentifier, requestConfig,
910                 WriteTransaction.CREATE_MISSING_PARENTS);
911     }
912
913     private void creatIngressEelementCountersContainerInConfig(ReadWriteTransaction transaction,
914             InstanceIdentifier<IngressElementCountersRequestConfig> ecrcIdentifier) {
915         IngressElementCountersRequestConfigBuilder iecrcb = new IngressElementCountersRequestConfigBuilder();
916         List<CounterRequests> counterRequests = new ArrayList<>();
917         iecrcb.setCounterRequests(counterRequests);
918         IngressElementCountersRequestConfig iecrc = iecrcb.build();
919         transaction.put(LogicalDatastoreType.CONFIGURATION, ecrcIdentifier, iecrc,
920                 WriteTransaction.CREATE_MISSING_PARENTS);
921     }
922
923     private void creatEgressEelementCountersContainerInConfig(ReadWriteTransaction transaction,
924             InstanceIdentifier<EgressElementCountersRequestConfig> ecrcIdentifier) {
925         EgressElementCountersRequestConfigBuilder eecrcb = new EgressElementCountersRequestConfigBuilder();
926         List<CounterRequests> counterRequests = new ArrayList<>();
927         eecrcb.setCounterRequests(counterRequests);
928         EgressElementCountersRequestConfig eecrc = eecrcb.build();
929         transaction.put(LogicalDatastoreType.CONFIGURATION, ecrcIdentifier, eecrc,
930                 WriteTransaction.CREATE_MISSING_PARENTS);
931     }
932
933     private Integer allocateId(String idKey) {
934         createIdPool();
935         AllocateIdInput getIdInput = new AllocateIdInputBuilder().setPoolName(CountersServiceUtils.COUNTERS_PULL_NAME)
936                 .setIdKey(idKey).build();
937         try {
938             Future<RpcResult<AllocateIdOutput>> result = idManagerService.allocateId(getIdInput);
939             RpcResult<AllocateIdOutput> rpcResult = result.get();
940             if (rpcResult.isSuccessful()) {
941                 return rpcResult.getResult().getIdValue().intValue();
942             } else {
943                 LOG.warn("RPC Call to Get Unique Id returned with Errors {}", rpcResult.getErrors());
944             }
945         } catch (InterruptedException | ExecutionException e) {
946             LOG.warn("Exception when getting Unique Id", e);
947         }
948         return null;
949     }
950
951     private void createIdPool() {
952         if (checkPoolExists()) {
953             return;
954         }
955         CreateIdPoolInput createPool = new CreateIdPoolInputBuilder()
956                 .setPoolName(CountersServiceUtils.COUNTERS_PULL_NAME).setLow(CountersServiceUtils.COUNTERS_PULL_START)
957                 .setHigh(CountersServiceUtils.COUNTERS_PULL_START + CountersServiceUtils.COUNTERS_PULL_END).build();
958         ListenableFuture<RpcResult<CreateIdPoolOutput>> result = idManagerService.createIdPool(createPool);
959         Futures.addCallback(result, new FutureCallback<RpcResult<CreateIdPoolOutput>>() {
960
961             @Override
962             public void onFailure(Throwable error) {
963                 LOG.error("Failed to create idPool for Aliveness Monitor Service", error);
964             }
965
966             @Override
967             public void onSuccess(@NonNull RpcResult<CreateIdPoolOutput> rpcResult) {
968                 if (rpcResult.isSuccessful()) {
969                     LOG.debug("Created IdPool for tap");
970                 } else {
971                     LOG.error("RPC to create Idpool failed {}", rpcResult.getErrors());
972                 }
973             }
974         }, MoreExecutors.directExecutor());
975     }
976
977     private void releaseId(String idKey) {
978         ReleaseIdInput idInput = new ReleaseIdInputBuilder().setPoolName(CountersServiceUtils.COUNTERS_PULL_NAME)
979                 .setIdKey(idKey).build();
980         try {
981             RpcResult<ReleaseIdOutput> rpcResult = idManagerService.releaseId(idInput).get();
982             if (!rpcResult.isSuccessful()) {
983                 LOG.warn("RPC Call to release Id with Key {} returned with Errors {}", idKey, rpcResult.getErrors());
984             }
985         } catch (InterruptedException | ExecutionException e) {
986             LOG.warn("Exception when releasing Id for key {}", idKey, e);
987         }
988     }
989
990     private boolean checkPoolExists() {
991         ReadOnlyTransaction roTransaction = db.newReadOnlyTransaction();
992         InstanceIdentifier<IdPool> path = InstanceIdentifier.create(IdPools.class).child(IdPool.class,
993                 new IdPoolKey(CountersServiceUtils.COUNTERS_PULL_NAME));
994         CheckedFuture<Optional<IdPool>, ReadFailedException> pool =
995                 roTransaction.read(LogicalDatastoreType.CONFIGURATION, path);
996         try {
997             Optional<IdPool> poolOpt = pool.get();
998             if (poolOpt.isPresent()) {
999                 return true;
1000             }
1001         } catch (InterruptedException | ExecutionException e) {
1002             return false;
1003         }
1004         return false;
1005     }
1006
1007     private boolean isIdenticalCounterRequestExist(String portId, String dirction, Filters filters,
1008             List<CounterRequests> counterRequests) {
1009         if (counterRequests.isEmpty()) {
1010             return false;
1011         }
1012
1013         for (CounterRequests counterRequest : counterRequests) {
1014             if (portId.equals(counterRequest.getPortId()) && dirction.equals(counterRequest.getTrafficDirection())) {
1015                 if (areFiltersEqual(filters, counterRequest.getFilters())) {
1016                     return true;
1017                 }
1018             }
1019         }
1020         return false;
1021     }
1022
1023     private boolean isIdenticalCounterRequestExist(String requesId, String portId, String dirction, Filters filters,
1024             List<CounterRequests> counterRequests) {
1025         if (counterRequests.isEmpty()) {
1026             return false;
1027         }
1028
1029         for (CounterRequests counterRequest : counterRequests) {
1030             if (portId.equals(counterRequest.getPortId()) && dirction.equals(counterRequest.getTrafficDirection())
1031                     && !counterRequest.key().getRequestId().equals(requesId)) {
1032                 if (areFiltersEqual(filters, counterRequest.getFilters())) {
1033                     return true;
1034                 }
1035             }
1036         }
1037         return false;
1038     }
1039
1040     private int getLportTag(String interfaceId) {
1041         return interfaceManager.getInterfaceInfo(interfaceId).getInterfaceTag();
1042     }
1043
1044     private BigInteger getDpn(String interfaceId) {
1045         return interfaceManager.getDpnForInterface(interfaceId);
1046     }
1047
1048     private List<ElementCountersRequest> createElementCounterRequest(String portId, int lportTag, BigInteger dpn,
1049             ElementCountersDirection direcrtion, Filters filters) {
1050         List<ElementCountersRequest> ecrList = new ArrayList<>();
1051         LOG.debug("getting element counters for port {}", portId);
1052         addElementCounterRequest(ecrList, portId, lportTag, dpn, direcrtion, filters);
1053
1054         logElementCounterRequests(ecrList);
1055
1056         return ecrList;
1057     }
1058 }