Merge "We already have a merged and validated flow entry. There is no need for extrac...
[controller.git] / opendaylight / config / config-manager / src / main / java / org / opendaylight / controller / config / manager / impl / DeadlockMonitor.java
1 package org.opendaylight.controller.config.manager.impl;
2
3 import org.opendaylight.controller.config.api.ModuleIdentifier;
4 import org.slf4j.Logger;
5 import org.slf4j.LoggerFactory;
6
7 import javax.annotation.Nullable;
8 import javax.annotation.concurrent.GuardedBy;
9 import java.util.concurrent.TimeUnit;
10
11 public class DeadlockMonitor implements AutoCloseable {
12     private static final Logger logger = LoggerFactory.getLogger(DeadlockMonitorRunnable.class);
13
14     private static final long WARN_AFTER_MILLIS = 5000;
15
16     private final TransactionIdentifier transactionIdentifier;
17     private final DeadlockMonitorRunnable thread;
18     @GuardedBy("this")
19     private ModuleIdentifierWithNanos moduleIdentifierWithNanos = new ModuleIdentifierWithNanos();
20
21     public DeadlockMonitor(TransactionIdentifier transactionIdentifier) {
22         this.transactionIdentifier = transactionIdentifier;
23         thread = new DeadlockMonitorRunnable();
24         thread.start();
25     }
26
27     public synchronized void setCurrentlyInstantiatedModule(ModuleIdentifier currentlyInstantiatedModule) {
28         this.moduleIdentifierWithNanos = new ModuleIdentifierWithNanos(currentlyInstantiatedModule);
29     }
30
31     public boolean isAlive() {
32         return thread.isAlive();
33     }
34
35     @Override
36     public void close() {
37         thread.interrupt();
38     }
39
40     @Override
41     public String toString() {
42         return "DeadlockMonitor{" + transactionIdentifier + '}';
43     }
44
45     private class DeadlockMonitorRunnable extends Thread {
46
47         private DeadlockMonitorRunnable() {
48             super(DeadlockMonitor.this.toString());
49         }
50
51         @Override
52         public void run() {
53             ModuleIdentifierWithNanos old = new ModuleIdentifierWithNanos(); // null moduleId
54             while (this.isInterrupted() == false) {
55                 ModuleIdentifierWithNanos copy = new ModuleIdentifierWithNanos(DeadlockMonitor.this.moduleIdentifierWithNanos);
56                 if (old.moduleIdentifier == null) {
57                     // started
58                     old = copy;
59                 } else if (old.moduleIdentifier != null && old.equals(copy)) {
60                     // is the getInstance() running longer than WARN_AFTER_MILLIS ?
61                     long runningTime = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - copy.nanoTime);
62                     if (runningTime > WARN_AFTER_MILLIS) {
63                         logger.warn("{} did not finish after {} ms", copy.moduleIdentifier, runningTime);
64                     }
65                 }
66                 try {
67                     sleep(1000);
68                 } catch (InterruptedException e) {
69                     interrupt();
70                 }
71             }
72             logger.trace("Exiting {}", this);
73         }
74
75         @Override
76         public String toString() {
77             return "DeadLockMonitorRunnable{" + transactionIdentifier + "}";
78         }
79     }
80
81     private class ModuleIdentifierWithNanos {
82         @Nullable
83         private final ModuleIdentifier moduleIdentifier;
84         private final long nanoTime;
85
86         private ModuleIdentifierWithNanos() {
87             moduleIdentifier = null;
88             nanoTime = System.nanoTime();
89         }
90
91         private ModuleIdentifierWithNanos(ModuleIdentifier moduleIdentifier) {
92             this.moduleIdentifier = moduleIdentifier;
93             nanoTime = System.nanoTime();
94         }
95
96         private ModuleIdentifierWithNanos(ModuleIdentifierWithNanos copy) {
97             moduleIdentifier = copy.moduleIdentifier;
98             nanoTime = copy.nanoTime;
99         }
100
101         @Override
102         public boolean equals(Object o) {
103             if (this == o) return true;
104             if (o == null || getClass() != o.getClass()) return false;
105
106             ModuleIdentifierWithNanos that = (ModuleIdentifierWithNanos) o;
107
108             if (nanoTime != that.nanoTime) return false;
109             if (moduleIdentifier != null ? !moduleIdentifier.equals(that.moduleIdentifier) : that.moduleIdentifier != null)
110                 return false;
111
112             return true;
113         }
114
115         @Override
116         public int hashCode() {
117             int result = moduleIdentifier != null ? moduleIdentifier.hashCode() : 0;
118             result = 31 * result + (int) (nanoTime ^ (nanoTime >>> 32));
119             return result;
120         }
121     }
122 }