blob: 9016ec25b0a76c08107dd6ef75c4533dffda3c35 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more contributor license
* agreements. See the NOTICE file distributed with this work for additional information regarding
* copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License. You may obtain a
* copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*/
package org.apache.geode.distributed.internal.deadlock;
import java.io.Serializable;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.apache.geode.annotations.internal.MakeNotStatic;
import org.apache.geode.internal.CopyOnWriteHashSet;
/**
* A singleton which keeps track of all of the dependency monitors registered in this VM.
*
* Dependency monitors track dependencies between threads that may not be known to the JVM. For
* example, a thread in one VM may be waiting for a response to a thread in another VM.
*
* {@link DependencyMonitor}s should register themselves with this class. Then, the
* {@link DeadlockDetector} will be able to query them for dependencies when finding deadlocks.
*
*
*/
public class DependencyMonitorManager {
@MakeNotStatic
private static final Set<DependencyMonitor> monitors =
new CopyOnWriteHashSet<DependencyMonitor>();
static {
// The DLockDependencyMonitor won't get loaded unless we add it here.
addMonitor(DLockDependencyMonitor.INSTANCE);
}
/**
* Register a dependency monitor.
*/
public static void addMonitor(DependencyMonitor monitor) {
monitors.add(monitor);
}
/**
* Unregister a dependency monitor.
*/
public static void removeMonitor(DependencyMonitor monitor) {
monitors.remove(monitor);
}
/**
* Get the set of all blocked threads and their dependencies in this VM, as reported by the
* dependency monitors registered with this manager.
*/
public static Set<Dependency<Thread, Serializable>> getBlockedThreads() {
Set<Dependency<Thread, Serializable>> blockedThreads =
new HashSet<Dependency<Thread, Serializable>>();
Thread[] allThreads = getAllThreads();
for (DependencyMonitor monitor : monitors) {
blockedThreads.addAll(monitor.getBlockedThreads(allThreads));
}
return blockedThreads;
}
/**
* Get the set of all resources which are held by threads in this VM, as reported by the
* dependency monitors registered with this manager.
*/
public static Set<Dependency<Serializable, Thread>> getHeldResources() {
Thread[] allThreads = getAllThreads();
Set<Dependency<Serializable, Thread>> heldResources =
new HashSet<Dependency<Serializable, Thread>>();
for (DependencyMonitor monitor : monitors) {
heldResources.addAll(monitor.getHeldResources(allThreads));
}
return heldResources;
}
/**
* Get all of the threads in this VM. TODO - do this more efficiently. TODO - move this to a more
* appropriate location.
*/
public static Thread[] getAllThreads() {
// Ok, this lame. This seems to be the easiest way
// to get all threads in java. Weak.
Map<Thread, StackTraceElement[]> allStacks = Thread.getAllStackTraces();
Thread[] results = new Thread[allStacks.size()];
results = allStacks.keySet().toArray(results);
return results;
}
}