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