1 package org.opendaylight.controller.config.manager.impl;
3 import org.opendaylight.controller.config.api.ModuleIdentifier;
4 import org.slf4j.Logger;
5 import org.slf4j.LoggerFactory;
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;
13 public class DeadlockMonitor implements AutoCloseable {
14 private static final Logger logger = LoggerFactory.getLogger(DeadlockMonitorRunnable.class);
16 private static final long WARN_AFTER_MILLIS = 5000;
18 private final TransactionIdentifier transactionIdentifier;
19 private final DeadlockMonitorRunnable thread;
21 private final Deque<ModuleIdentifierWithNanos> moduleIdentifierWithNanosStack = new LinkedList<>();
23 private ModuleIdentifierWithNanos top = ModuleIdentifierWithNanos.EMPTY;
25 public DeadlockMonitor(TransactionIdentifier transactionIdentifier) {
26 this.transactionIdentifier = transactionIdentifier;
27 thread = new DeadlockMonitorRunnable();
31 public synchronized void setCurrentlyInstantiatedModule(ModuleIdentifier currentlyInstantiatedModule) {
33 boolean popping = currentlyInstantiatedModule == null;
35 moduleIdentifierWithNanosStack.pop();
36 if (moduleIdentifierWithNanosStack.isEmpty()) {
37 top = ModuleIdentifierWithNanos.EMPTY;
39 top = moduleIdentifierWithNanosStack.peekLast();
42 ModuleIdentifierWithNanos current = new ModuleIdentifierWithNanos(currentlyInstantiatedModule);
43 moduleIdentifierWithNanosStack.push(current);
46 logger.trace("setCurrentlyInstantiatedModule {}, top {}", currentlyInstantiatedModule, top);
49 public boolean isAlive() {
50 return thread.isAlive();
59 public String toString() {
60 return "DeadlockMonitor{" + transactionIdentifier + '}';
63 private class DeadlockMonitorRunnable extends Thread {
65 private DeadlockMonitorRunnable() {
66 super(DeadlockMonitor.this.toString());
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) {
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);
86 } catch (InterruptedException e) {
90 logger.trace("Exiting {}", this);
94 public String toString() {
95 return "DeadLockMonitorRunnable{" + transactionIdentifier + "}";
102 private static class ModuleIdentifierWithNanos {
103 private static ModuleIdentifierWithNanos EMPTY = new ModuleIdentifierWithNanos();
105 private final ModuleIdentifier moduleIdentifier;
107 private final long nanoTime;
109 private ModuleIdentifierWithNanos() {
110 this((ModuleIdentifier)null);
113 private ModuleIdentifierWithNanos(ModuleIdentifier moduleIdentifier) {
114 this.moduleIdentifier = moduleIdentifier;
115 nanoTime = System.nanoTime();
118 private ModuleIdentifierWithNanos(ModuleIdentifierWithNanos copy) {
119 moduleIdentifier = copy.moduleIdentifier;
120 nanoTime = copy.nanoTime;
124 public boolean equals(Object o) {
125 if (this == o) return true;
126 if (o == null || getClass() != o.getClass()) return false;
128 ModuleIdentifierWithNanos that = (ModuleIdentifierWithNanos) o;
130 if (nanoTime != that.nanoTime) return false;
131 if (moduleIdentifier != null ? !moduleIdentifier.equals(that.moduleIdentifier) : that.moduleIdentifier != null)
138 public int hashCode() {
139 int result = moduleIdentifier != null ? moduleIdentifier.hashCode() : 0;
140 result = 31 * result + (int) (nanoTime ^ (nanoTime >>> 32));
145 public String toString() {
146 return "ModuleIdentifierWithNanos{" +