Author: mir
Date: Thu Sep  2 15:11:57 2010
New Revision: 991968

URL: http://svn.apache.org/viewvc?rev=991968&view=rev
Log:
CLEREZZA-295: implemented rdf lock debugging capabilities

Added:
    
incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.rdf.core/src/main/java/org/apache/clerezza/rdf/core/access/debug/
    
incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.rdf.core/src/main/java/org/apache/clerezza/rdf/core/access/debug/ReadLockDebug.java
    
incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.rdf.core/src/main/java/org/apache/clerezza/rdf/core/access/debug/ReentrantReadWriteLockTracker.java
    
incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.rdf.core/src/main/java/org/apache/clerezza/rdf/core/access/debug/WriteLockDebug.java
    
incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.rdf.locking/
    
incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.rdf.locking/pom.xml
    
incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.rdf.locking/src/
    
incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.rdf.locking/src/main/
    
incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.rdf.locking/src/main/java/
    
incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.rdf.locking/src/main/java/org/
    
incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.rdf.locking/src/main/java/org/apache/
    
incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.rdf.locking/src/main/java/org/apache/clerezza/
    
incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.rdf.locking/src/main/java/org/apache/clerezza/rdf/
    
incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.rdf.locking/src/main/java/org/apache/clerezza/rdf/locking/
    
incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.rdf.locking/src/main/java/org/apache/clerezza/rdf/locking/LockOverview.java
Modified:
    
incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.rdf.core/src/main/java/org/apache/clerezza/rdf/core/access/LockableMGraphWrapper.java

Modified: 
incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.rdf.core/src/main/java/org/apache/clerezza/rdf/core/access/LockableMGraphWrapper.java
URL: 
http://svn.apache.org/viewvc/incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.rdf.core/src/main/java/org/apache/clerezza/rdf/core/access/LockableMGraphWrapper.java?rev=991968&r1=991967&r2=991968&view=diff
==============================================================================
--- 
incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.rdf.core/src/main/java/org/apache/clerezza/rdf/core/access/LockableMGraphWrapper.java
 (original)
+++ 
incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.rdf.core/src/main/java/org/apache/clerezza/rdf/core/access/LockableMGraphWrapper.java
 Thu Sep  2 15:11:57 2010
@@ -18,6 +18,7 @@
  */
 package org.apache.clerezza.rdf.core.access;
 
+import org.apache.clerezza.rdf.core.access.debug.ReentrantReadWriteLockTracker;
 import java.util.Collection;
 import java.util.Iterator;
 import java.util.concurrent.locks.Lock;
@@ -40,7 +41,17 @@ import org.apache.clerezza.rdf.core.even
  */
 public class LockableMGraphWrapper implements LockableMGraph {
 
-       private final ReadWriteLock lock = new ReentrantReadWriteLock();
+
+       private static final String DEBUG_MODE = "rdfLocksDebugging";
+       private final ReadWriteLock lock;
+       {
+               String debugMode = System.getProperty(DEBUG_MODE);
+               if (debugMode != null && 
debugMode.toLowerCase().equals("true")) {
+                       lock = new ReentrantReadWriteLockTracker();
+               } else {
+                       lock = new ReentrantReadWriteLock();
+               }
+       }
        private final Lock readLock = lock.readLock();
        private final Lock writeLock = lock.writeLock();
        private final MGraph wrapped;

Added: 
incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.rdf.core/src/main/java/org/apache/clerezza/rdf/core/access/debug/ReadLockDebug.java
URL: 
http://svn.apache.org/viewvc/incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.rdf.core/src/main/java/org/apache/clerezza/rdf/core/access/debug/ReadLockDebug.java?rev=991968&view=auto
==============================================================================
--- 
incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.rdf.core/src/main/java/org/apache/clerezza/rdf/core/access/debug/ReadLockDebug.java
 (added)
+++ 
incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.rdf.core/src/main/java/org/apache/clerezza/rdf/core/access/debug/ReadLockDebug.java
 Thu Sep  2 15:11:57 2010
@@ -0,0 +1,85 @@
+/*
+ * 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.clerezza.rdf.core.access.debug;
+
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.locks.Condition;
+import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock;
+
+/**
+ *
+ * @author mir
+ */
+public class ReadLockDebug extends ReadLock {
+
+       ReentrantReadWriteLockTracker lock;
+       StackTraceElement[] stackTrace;
+
+       ReadLock readLock;
+       public ReadLockDebug(ReentrantReadWriteLockTracker lock) {
+               super(lock);
+               this.lock = lock;
+               this.readLock = lock.realReadLock();
+       }
+
+       @Override
+       public void lock() {
+               readLock.lock();
+               lock.addLockedReadLock(this);
+               stackTrace = Thread.currentThread().getStackTrace();
+       }
+
+       @Override
+       public void lockInterruptibly() throws InterruptedException {
+               readLock.lockInterruptibly();
+       }
+
+       @Override
+       public Condition newCondition() {
+               return readLock.newCondition();
+       }
+
+       @Override
+       public String toString() {
+               return readLock.toString();
+       }
+
+       @Override
+       public boolean tryLock() {
+               return readLock.tryLock();
+       }
+
+       @Override
+       public boolean tryLock(long timeout, TimeUnit unit) throws 
InterruptedException {
+               return readLock.tryLock(timeout, unit);
+       }
+
+       @Override
+       public void unlock() {
+               readLock.unlock();
+               lock.removeReadLock(this);
+               stackTrace = null;
+       }
+
+       public StackTraceElement[] getStackTrace() {
+               return stackTrace;
+       }
+
+}

Added: 
incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.rdf.core/src/main/java/org/apache/clerezza/rdf/core/access/debug/ReentrantReadWriteLockTracker.java
URL: 
http://svn.apache.org/viewvc/incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.rdf.core/src/main/java/org/apache/clerezza/rdf/core/access/debug/ReentrantReadWriteLockTracker.java?rev=991968&view=auto
==============================================================================
--- 
incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.rdf.core/src/main/java/org/apache/clerezza/rdf/core/access/debug/ReentrantReadWriteLockTracker.java
 (added)
+++ 
incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.rdf.core/src/main/java/org/apache/clerezza/rdf/core/access/debug/ReentrantReadWriteLockTracker.java
 Thu Sep  2 15:11:57 2010
@@ -0,0 +1,133 @@
+/*
+ * 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.clerezza.rdf.core.access.debug;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.concurrent.locks.Condition;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+
+/**
+ *
+ * @author mir
+ */
+public class ReentrantReadWriteLockTracker extends ReentrantReadWriteLock {
+
+
+       private Set<ReadLockDebug> lockedReadLocks = 
Collections.synchronizedSet(new HashSet<ReadLockDebug>());
+       private final WriteLockDebug writeLock = new WriteLockDebug(this);
+       @Override
+       protected Thread getOwner() {
+               return super.getOwner();
+       }
+
+       @Override
+       protected Collection<Thread> getQueuedReaderThreads() {
+               return super.getQueuedReaderThreads();
+       }
+
+       @Override
+       protected Collection<Thread> getQueuedThreads() {
+               return super.getQueuedThreads();
+       }
+
+       @Override
+       protected Collection<Thread> getQueuedWriterThreads() {
+               return super.getQueuedWriterThreads();
+       }
+
+       @Override
+       public int getReadHoldCount() {
+               return super.getReadHoldCount();
+       }
+
+       @Override
+       public int getReadLockCount() {
+               return super.getReadLockCount();
+       }
+
+       @Override
+       public int getWaitQueueLength(Condition condition) {
+               return super.getWaitQueueLength(condition);
+       }
+
+       @Override
+       protected Collection<Thread> getWaitingThreads(Condition condition) {
+               return super.getWaitingThreads(condition);
+       }
+
+       @Override
+       public int getWriteHoldCount() {
+               return super.getWriteHoldCount();
+       }
+
+       @Override
+       public boolean hasWaiters(Condition condition) {
+               return super.hasWaiters(condition);
+       }
+
+       @Override
+       public boolean isWriteLocked() {
+               return super.isWriteLocked();
+       }
+
+       @Override
+       public boolean isWriteLockedByCurrentThread() {
+               return super.isWriteLockedByCurrentThread();
+       }
+
+       @Override
+       public ReadLock readLock() {
+               return new ReadLockDebug(this);
+       }
+
+       ReadLock realReadLock() {
+               return super.readLock();
+       }
+
+       WriteLock realWriteLock() {
+               return super.writeLock();
+       }
+
+       @Override
+       public String toString() {
+               return super.toString();
+       }
+
+       @Override
+       public WriteLockDebug writeLock() {
+               return writeLock;
+       }
+
+       void addLockedReadLock(ReadLockDebug lock) {
+               lockedReadLocks.add(lock);
+       }
+
+       void removeReadLock(ReadLockDebug lock) {
+               lockedReadLocks.remove(lock);
+       }
+
+       public Set<ReadLockDebug> getLockedReadLocks() {
+               return lockedReadLocks;
+       }
+
+
+}

Added: 
incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.rdf.core/src/main/java/org/apache/clerezza/rdf/core/access/debug/WriteLockDebug.java
URL: 
http://svn.apache.org/viewvc/incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.rdf.core/src/main/java/org/apache/clerezza/rdf/core/access/debug/WriteLockDebug.java?rev=991968&view=auto
==============================================================================
--- 
incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.rdf.core/src/main/java/org/apache/clerezza/rdf/core/access/debug/WriteLockDebug.java
 (added)
+++ 
incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.rdf.core/src/main/java/org/apache/clerezza/rdf/core/access/debug/WriteLockDebug.java
 Thu Sep  2 15:11:57 2010
@@ -0,0 +1,89 @@
+/*
+ * 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.clerezza.rdf.core.access.debug;
+
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.locks.Condition;
+import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock;
+
+/**
+ *
+ * @author mir
+ */
+public class WriteLockDebug extends WriteLock {
+
+       private ReentrantReadWriteLockTracker lock;
+       private WriteLock writeLock;
+       private StackTraceElement[] stackTrace;
+
+       public WriteLockDebug(ReentrantReadWriteLockTracker lock) {
+               super(lock);
+               this.lock = lock;
+               this.writeLock = lock.realWriteLock();
+       }
+
+       @Override
+       public int getHoldCount() {
+               return writeLock.getHoldCount();
+       }
+
+       @Override
+       public boolean isHeldByCurrentThread() {
+               return writeLock.isHeldByCurrentThread();
+       }
+
+       @Override
+       public void lock() {
+               writeLock.lock();
+               stackTrace = Thread.currentThread().getStackTrace();
+       }
+
+       @Override
+       public void lockInterruptibly() throws InterruptedException {
+               writeLock.lockInterruptibly();
+       }
+
+       @Override
+       public Condition newCondition() {
+               return writeLock.newCondition();
+       }
+
+       @Override
+       public boolean tryLock() {
+               return writeLock.tryLock();
+       }
+
+       @Override
+       public boolean tryLock(long timeout, TimeUnit unit) throws 
InterruptedException {
+               return writeLock.tryLock(timeout, unit);
+       }
+
+       @Override
+       public void unlock() {
+               writeLock.unlock();
+               stackTrace = null;
+       }
+
+       public StackTraceElement[] getStackTrace() {
+               return stackTrace;
+       }
+
+
+}

Added: 
incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.rdf.locking/pom.xml
URL: 
http://svn.apache.org/viewvc/incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.rdf.locking/pom.xml?rev=991968&view=auto
==============================================================================
--- 
incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.rdf.locking/pom.xml
 (added)
+++ 
incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.rdf.locking/pom.xml
 Thu Sep  2 15:11:57 2010
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"; 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";>
+       <modelVersion>4.0.0</modelVersion>
+
+       <parent>
+               <groupId>org.apache.clerezza</groupId>
+               <artifactId>org.apache.clerezza.parent</artifactId>
+               <version>0.2-incubating-SNAPSHOT</version>
+       </parent>
+       <groupId>org.apache.clerezza</groupId>
+       <artifactId>org.apache.clerezza.rdf.locking</artifactId>
+       <version>0.1-incubating-SNAPSHOT</version>
+       
+       <packaging>bundle</packaging>
+       <name>Clerezza - RDF locking</name>
+       <description>Provides a web page containig an overview of graph 
locks.</description>
+
+       <dependencies>
+               <dependency>
+                       <groupId>org.apache.felix</groupId>
+                       
<artifactId>org.apache.felix.scr.annotations</artifactId>
+               </dependency>
+               <dependency>
+                       <groupId>javax.ws.rs</groupId>
+                       <artifactId>jsr311-api</artifactId>
+               </dependency>
+               <dependency>
+                       <groupId>org.apache.clerezza</groupId>
+                       
<artifactId>org.apache.clerezza.platform.typerendering.core</artifactId>
+               </dependency>
+       </dependencies>
+</project>

Added: 
incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.rdf.locking/src/main/java/org/apache/clerezza/rdf/locking/LockOverview.java
URL: 
http://svn.apache.org/viewvc/incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.rdf.locking/src/main/java/org/apache/clerezza/rdf/locking/LockOverview.java?rev=991968&view=auto
==============================================================================
--- 
incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.rdf.locking/src/main/java/org/apache/clerezza/rdf/locking/LockOverview.java
 (added)
+++ 
incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.rdf.locking/src/main/java/org/apache/clerezza/rdf/locking/LockOverview.java
 Thu Sep  2 15:11:57 2010
@@ -0,0 +1,146 @@
+/*
+ * 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.clerezza.rdf.locking;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import org.apache.clerezza.rdf.core.UriRef;
+import org.apache.clerezza.rdf.core.access.TcManager;
+import org.apache.clerezza.rdf.core.access.debug.ReadLockDebug;
+import org.apache.clerezza.rdf.core.access.debug.ReentrantReadWriteLockTracker;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Property;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.Service;
+
+/**
+ * Provides an overview page of all locks of all graphs.
+ * @author mir
+ */
+...@component()
+...@service(value = Object.class)
+...@property(name = "javax.ws.rs", boolValue = true)
+...@path("/locks")
+public class LockOverview {
+
+       @Reference
+       TcManager tcManager;
+
+       @GET
+       public String getOverview() {
+               Set<Thread> threadSet = getAllThreads();
+               Iterator<UriRef> mGraphUris = 
tcManager.listMGraphs().iterator();
+
+               StringWriter stringWriter = new StringWriter();
+               PrintWriter printWriter = new PrintWriter(stringWriter);
+               while (mGraphUris.hasNext()) {
+                       UriRef uriRef = mGraphUris.next();
+                       ReentrantReadWriteLock lock = (ReentrantReadWriteLock) 
tcManager.getMGraph(uriRef).getLock();
+                       int readLockCount = lock.getReadLockCount();
+                       printWriter.append(uriRef.getUnicodeString());
+                       printWriter.append("\n");
+                       printWriter.append("Read-Lock count:    " + 
readLockCount);
+                       printWriter.append("\n");
+                       printWriter.append("Write-Locked:       " + 
(lock.isWriteLocked() ? "YES" : "NO"));
+                       printWriter.append("\n");
+                       printWriter.append("Has queued threads: " + 
(lock.hasQueuedThreads() ? "YES" : "NO"));
+                       printWriter.append("\n");
+                       if (readLockCount > 0 && lock instanceof 
ReentrantReadWriteLockTracker) {
+                               ReentrantReadWriteLockTracker debugLock = 
(ReentrantReadWriteLockTracker) lock;
+                               printWriter.append("Threads holding read-lock: 
\n");
+                               Set<ReadLockDebug> lockedReadLocks = 
debugLock.getLockedReadLocks();
+                               for (ReadLockDebug readLockDebug : 
lockedReadLocks) {
+                                       
printStackTrace(readLockDebug.getStackTrace(), printWriter);
+                                       printWriter.append("\n");
+                               }
+                               printWriter.append("\n");
+                       }
+                       if (lock.isWriteLocked() && lock instanceof 
ReentrantReadWriteLockTracker) {
+                               ReentrantReadWriteLockTracker debugLock = 
(ReentrantReadWriteLockTracker) lock;
+                               printWriter.append("Thread holding write-lock: 
\n");
+                               
printStackTrace(debugLock.writeLock().getStackTrace(), printWriter);
+                               printWriter.append("\n");
+                       }
+                       printWriter.append("Queue length:       " + 
lock.getQueueLength());
+                       printWriter.append("\n");
+                       printWriter.append("Queued threads: ");
+                       printWriter.append("\n");
+                       printQueuedThreads(lock, printWriter, threadSet);
+                       
printWriter.append("----------------------------------------------------");
+                       printWriter.append("\n");
+
+               }
+               return stringWriter.toString();
+       }
+
+       private void printQueuedThreads(ReentrantReadWriteLock lock, 
PrintWriter printWriter,
+                       Set<Thread> threadSet) {
+               for (Thread thread : threadSet) {
+                       if (lock.hasQueuedThread(thread)) {
+                               printWriter.append("" + thread.getId());
+                               printStackTrace(thread.getStackTrace(), 
printWriter);
+                               printWriter.append("\n");
+                       }
+               }
+       }
+
+       private void printStackTrace(StackTraceElement[] stackTrace, 
PrintWriter printWriter) {
+               Throwable throwable = new Throwable();
+               throwable.setStackTrace(stackTrace);
+               throwable.printStackTrace(printWriter);
+       }
+
+       public Set<Thread> getAllThreads() {
+               // Find the root thread group
+               ThreadGroup root = 
Thread.currentThread().getThreadGroup().getParent();
+               while (root.getParent() != null) {
+                       root = root.getParent();
+               }
+               HashSet<Thread> threadSet = new HashSet<Thread>();
+               visit(root, 0, threadSet);
+               return threadSet;
+       }
+
+       public void visit(ThreadGroup group, int level, HashSet<Thread> 
threadSet) {
+               // Get threads in `group'
+               int numThreads = group.activeCount();
+               Thread[] threads = new Thread[numThreads * 2];
+               numThreads = group.enumerate(threads, false);
+               // Enumerate each thread in `group'
+               for (int i = 0; i < numThreads; i++) {
+                       // Get thread
+                       Thread thread = threads[i];
+                       threadSet.add(thread);
+               }
+               // Get thread subgroups of `group'
+               int numGroups = group.activeGroupCount();
+               ThreadGroup[] groups = new ThreadGroup[numGroups * 2];
+               numGroups = group.enumerate(groups, false);
+               // Recursively visit each subgroup
+               for (int i = 0; i < numGroups; i++) {
+                       visit(groups[i], level + 1, threadSet);
+               }
+       }
+}


Reply via email to