Bump odlparent to 5.0.0
[openflowplugin.git] / openflowplugin-impl / src / main / java / org / opendaylight / openflowplugin / impl / statistics / StatisticsPollingService.java
1 /*
2  * Copyright (c) 2017 Pantheon Technologies s.r.o. 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.openflowplugin.impl.statistics;
9
10 import com.google.common.util.concurrent.AbstractScheduledService;
11 import com.google.common.util.concurrent.FutureCallback;
12 import com.google.common.util.concurrent.Futures;
13 import com.google.common.util.concurrent.ListenableFuture;
14 import com.google.common.util.concurrent.MoreExecutors;
15 import com.google.common.util.concurrent.Service;
16 import com.google.common.util.concurrent.SettableFuture;
17 import java.util.concurrent.CancellationException;
18 import java.util.concurrent.CompletableFuture;
19 import java.util.concurrent.TimeUnit;
20 import java.util.function.Supplier;
21 import javax.annotation.Nonnull;
22 import org.opendaylight.openflowplugin.api.ConnectionException;
23
24 public class StatisticsPollingService extends AbstractScheduledService {
25     private static final long DEFAULT_STATS_TIMEOUT = 50000;
26
27     private final TimeCounter counter;
28     private final long pollingInterval;
29     private final long maximumTimerDelay;
30     private final Supplier<ListenableFuture<Boolean>> gatheringSupplier;
31     private final SettableFuture<Void> future = SettableFuture.create();
32
33     StatisticsPollingService(@Nonnull final TimeCounter counter,
34                              final long pollingInterval,
35                              final long maximumTimerDelay,
36                              @Nonnull final Supplier<ListenableFuture<Boolean>> gatheringSupplier) {
37         this.counter = counter;
38         this.pollingInterval = pollingInterval;
39         this.maximumTimerDelay = maximumTimerDelay;
40         this.gatheringSupplier = gatheringSupplier;
41         this.addListener(new StatisticsPollingServiceListener(), MoreExecutors.directExecutor());
42     }
43
44     ListenableFuture<Void> stop() {
45         stopAsync();
46         return future;
47     }
48
49     @Override
50     protected void startUp() {
51         counter.markStart();
52     }
53
54     @Override
55     protected void runOneIteration() throws Exception {
56         final long averageTime = counter.getAverageTimeBetweenMarks();
57         final long statsTimeout = averageTime > 0 ? 3 * averageTime : DEFAULT_STATS_TIMEOUT;
58         final CompletableFuture<Boolean> waitFuture = new CompletableFuture<>();
59
60         Futures.addCallback(gatheringSupplier.get(), new FutureCallback<Boolean>() {
61             @Override
62             public void onSuccess(final Boolean result) {
63                 waitFuture.complete(result);
64             }
65
66             @Override
67             public void onFailure(final Throwable throwable) {
68                 waitFuture.completeExceptionally(throwable);
69             }
70         }, MoreExecutors.directExecutor());
71
72         try {
73             waitFuture.get(statsTimeout, TimeUnit.MILLISECONDS);
74         } finally {
75             counter.addTimeMark();
76         }
77     }
78
79     @Override
80     protected Scheduler scheduler() {
81         final long averageStatisticsGatheringTime = counter.getAverageTimeBetweenMarks();
82         long currentTimerDelay = pollingInterval;
83
84         if (averageStatisticsGatheringTime > currentTimerDelay) {
85             currentTimerDelay = averageStatisticsGatheringTime;
86
87             if (currentTimerDelay > maximumTimerDelay) {
88                 currentTimerDelay = maximumTimerDelay;
89             }
90         }
91
92         return Scheduler.newFixedDelaySchedule(currentTimerDelay, currentTimerDelay, TimeUnit.MILLISECONDS);
93     }
94
95     private final class StatisticsPollingServiceListener extends Service.Listener {
96         @Override
97         public void terminated(final Service.State from) {
98             super.terminated(from);
99             future.set(null);
100         }
101
102         @Override
103         public void failed(final Service.State from, final Throwable failure) {
104             super.failed(from, failure);
105             if (!(failure instanceof CancellationException) && !(failure instanceof ConnectionException)) {
106                 future.setException(failure);
107             } else {
108                 future.set(null);
109             }
110         }
111     }
112 }