1 package org.opendaylight.controller.config.manager.impl;
3 import java.util.Deque;
4 import java.util.LinkedList;
5 import java.util.concurrent.TimeUnit;
6 import javax.annotation.Nullable;
7 import javax.annotation.concurrent.GuardedBy;
8 import org.opendaylight.controller.config.api.ModuleIdentifier;
9 import org.slf4j.Logger;
10 import org.slf4j.LoggerFactory;
12 public class DeadlockMonitor implements AutoCloseable {
13 private static final Logger LOG = LoggerFactory.getLogger(DeadlockMonitor.class);
15 private static final long WARN_AFTER_MILLIS = 5000;
17 private final TransactionIdentifier transactionIdentifier;
18 private final DeadlockMonitorRunnable thread;
20 private final Deque<ModuleIdentifierWithNanos> moduleIdentifierWithNanosStack = new LinkedList<>();
22 private ModuleIdentifierWithNanos top = ModuleIdentifierWithNanos.EMPTY;
24 public DeadlockMonitor(TransactionIdentifier transactionIdentifier) {
25 this.transactionIdentifier = transactionIdentifier;
26 thread = new DeadlockMonitorRunnable();
30 public synchronized void setCurrentlyInstantiatedModule(ModuleIdentifier currentlyInstantiatedModule) {
32 boolean popping = currentlyInstantiatedModule == null;
34 moduleIdentifierWithNanosStack.pop();
35 if (moduleIdentifierWithNanosStack.isEmpty()) {
36 top = ModuleIdentifierWithNanos.EMPTY;
38 top = moduleIdentifierWithNanosStack.peekLast();
41 ModuleIdentifierWithNanos current = new ModuleIdentifierWithNanos(currentlyInstantiatedModule);
42 moduleIdentifierWithNanosStack.push(current);
45 LOG.trace("setCurrentlyInstantiatedModule {}, top {}", currentlyInstantiatedModule, top);
48 public boolean isAlive() {
49 return thread.isAlive();
58 public String toString() {
59 return "DeadlockMonitor{" + transactionIdentifier + '}';
62 private class DeadlockMonitorRunnable extends Thread {
64 private DeadlockMonitorRunnable() {
65 super(DeadlockMonitor.this.toString());
70 ModuleIdentifierWithNanos old = new ModuleIdentifierWithNanos(); // null moduleId
71 while (this.isInterrupted() == false) {
72 ModuleIdentifierWithNanos copy = new ModuleIdentifierWithNanos(DeadlockMonitor.this.top);
73 if (old.moduleIdentifier == null || old.equals(copy) == false) {
77 // is the getInstance() running longer than WARN_AFTER_MILLIS ?
78 long runningTime = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - copy.nanoTime);
79 if (runningTime > WARN_AFTER_MILLIS) {
80 LOG.warn("{} did not finish after {} ms", copy.moduleIdentifier, runningTime);
85 } catch (InterruptedException e) {
89 LOG.trace("Exiting {}", this);
93 public String toString() {
94 return "DeadLockMonitorRunnable{" + transactionIdentifier + "}";
101 private static class ModuleIdentifierWithNanos {
102 private static ModuleIdentifierWithNanos EMPTY = new ModuleIdentifierWithNanos();
104 private final ModuleIdentifier moduleIdentifier;
106 private final long nanoTime;
108 private ModuleIdentifierWithNanos() {
109 this((ModuleIdentifier)null);
112 private ModuleIdentifierWithNanos(ModuleIdentifier moduleIdentifier) {
113 this.moduleIdentifier = moduleIdentifier;
114 nanoTime = System.nanoTime();
117 private ModuleIdentifierWithNanos(ModuleIdentifierWithNanos copy) {
118 moduleIdentifier = copy.moduleIdentifier;
119 nanoTime = copy.nanoTime;
123 public boolean equals(Object o) {
127 if (o == null || getClass() != o.getClass()) {
131 ModuleIdentifierWithNanos that = (ModuleIdentifierWithNanos) o;
133 if (nanoTime != that.nanoTime) {
136 if (moduleIdentifier != null ? !moduleIdentifier.equals(that.moduleIdentifier) : that.moduleIdentifier != null) {
144 public int hashCode() {
145 int result = moduleIdentifier != null ? moduleIdentifier.hashCode() : 0;
146 result = 31 * result + (int) (nanoTime ^ (nanoTime >>> 32));
151 public String toString() {
152 return "ModuleIdentifierWithNanos{" +