Merge "Fixed typo in test name. Temporary ignore test."
[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.Deque;
10 import java.util.LinkedList;
11 import java.util.concurrent.TimeUnit;
12
13 public class DeadlockMonitor implements AutoCloseable {
14     private static final Logger logger = LoggerFactory.getLogger(DeadlockMonitorRunnable.class);
15
16     private static final long WARN_AFTER_MILLIS = 5000;
17
18     private final TransactionIdentifier transactionIdentifier;
19     private final DeadlockMonitorRunnable thread;
20     @GuardedBy("this")
21     private final Deque<ModuleIdentifierWithNanos> moduleIdentifierWithNanosStack = new LinkedList<>();
22     @GuardedBy("this")
23     private ModuleIdentifierWithNanos top = ModuleIdentifierWithNanos.EMPTY;
24
25     public DeadlockMonitor(TransactionIdentifier transactionIdentifier) {
26         this.transactionIdentifier = transactionIdentifier;
27         thread = new DeadlockMonitorRunnable();
28         thread.start();
29     }
30
31     public synchronized void setCurrentlyInstantiatedModule(ModuleIdentifier currentlyInstantiatedModule) {
32
33         boolean popping = currentlyInstantiatedModule == null;
34         if (popping) {
35             moduleIdentifierWithNanosStack.pop();
36             if (moduleIdentifierWithNanosStack.isEmpty()) {
37                 top = ModuleIdentifierWithNanos.EMPTY;
38             } else {
39                 top = moduleIdentifierWithNanosStack.peekLast();
40             }
41         } else {
42             ModuleIdentifierWithNanos current = new ModuleIdentifierWithNanos(currentlyInstantiatedModule);
43             moduleIdentifierWithNanosStack.push(current);
44             top = current;
45         }
46         logger.trace("setCurrentlyInstantiatedModule {}, top {}", currentlyInstantiatedModule, top);
47     }
48
49     public boolean isAlive() {
50         return thread.isAlive();
51     }
52
53     @Override
54     public void close() {
55         thread.interrupt();
56     }
57
58     @Override
59     public String toString() {
60         return "DeadlockMonitor{" + transactionIdentifier + '}';
61     }
62
63     private class DeadlockMonitorRunnable extends Thread {
64
65         private DeadlockMonitorRunnable() {
66             super(DeadlockMonitor.this.toString());
67         }
68
69         @Override
70         public void run() {
71             ModuleIdentifierWithNanos old = new ModuleIdentifierWithNanos(); // null moduleId
72             while (this.isInterrupted() == false) {
73                 ModuleIdentifierWithNanos copy = new ModuleIdentifierWithNanos(DeadlockMonitor.this.top);
74                 if (old.moduleIdentifier == null || old.equals(copy) == false) {
75                     // started
76                     old = copy;
77                 } else {
78                     // is the getInstance() running longer than WARN_AFTER_MILLIS ?
79                     long runningTime = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - copy.nanoTime);
80                     if (runningTime > WARN_AFTER_MILLIS) {
81                         logger.warn("{} did not finish after {} ms", copy.moduleIdentifier, runningTime);
82                     }
83                 }
84                 try {
85                     sleep(1000);
86                 } catch (InterruptedException e) {
87                     interrupt();
88                 }
89             }
90             logger.trace("Exiting {}", this);
91         }
92
93         @Override
94         public String toString() {
95             return "DeadLockMonitorRunnable{" + transactionIdentifier + "}";
96         }
97     }
98
99
100
101
102     private static class ModuleIdentifierWithNanos {
103         private static ModuleIdentifierWithNanos EMPTY = new ModuleIdentifierWithNanos();
104         @Nullable
105         private final ModuleIdentifier moduleIdentifier;
106
107         private final long nanoTime;
108
109         private ModuleIdentifierWithNanos() {
110             this((ModuleIdentifier)null);
111         }
112
113         private ModuleIdentifierWithNanos(ModuleIdentifier moduleIdentifier) {
114             this.moduleIdentifier = moduleIdentifier;
115             nanoTime = System.nanoTime();
116         }
117
118         private ModuleIdentifierWithNanos(ModuleIdentifierWithNanos copy) {
119             moduleIdentifier = copy.moduleIdentifier;
120             nanoTime = copy.nanoTime;
121         }
122
123         @Override
124         public boolean equals(Object o) {
125             if (this == o) return true;
126             if (o == null || getClass() != o.getClass()) return false;
127
128             ModuleIdentifierWithNanos that = (ModuleIdentifierWithNanos) o;
129
130             if (nanoTime != that.nanoTime) return false;
131             if (moduleIdentifier != null ? !moduleIdentifier.equals(that.moduleIdentifier) : that.moduleIdentifier != null)
132                 return false;
133
134             return true;
135         }
136
137         @Override
138         public int hashCode() {
139             int result = moduleIdentifier != null ? moduleIdentifier.hashCode() : 0;
140             result = 31 * result + (int) (nanoTime ^ (nanoTime >>> 32));
141             return result;
142         }
143
144         @Override
145         public String toString() {
146             return "ModuleIdentifierWithNanos{" +
147                     moduleIdentifier +
148                     '}';
149         }
150     }
151 }