Merge branch 'master' of github.com:trustin/netty
This commit is contained in:
commit
6f7e2606a1
@ -42,7 +42,6 @@ import org.jboss.netty.channel.ChannelStateEvent;
|
||||
import org.jboss.netty.channel.MessageEvent;
|
||||
import org.jboss.netty.logging.InternalLogger;
|
||||
import org.jboss.netty.logging.InternalLoggerFactory;
|
||||
import org.jboss.netty.util.ThreadRenamingRunnable;
|
||||
import org.jboss.netty.util.internal.DeadLockProofWorker;
|
||||
import org.jboss.netty.util.internal.LinkedTransferQueue;
|
||||
|
||||
@ -196,10 +195,7 @@ class NioClientSocketPipelineSink extends AbstractChannelSink {
|
||||
// Start the worker thread with the new Selector.
|
||||
boolean success = false;
|
||||
try {
|
||||
DeadLockProofWorker.start(
|
||||
bossExecutor,
|
||||
new ThreadRenamingRunnable(
|
||||
this, "NewIO", "ClientBoss", null, String.valueOf(id), null));
|
||||
DeadLockProofWorker.start(bossExecutor, this);
|
||||
success = true;
|
||||
} finally {
|
||||
if (!success) {
|
||||
|
@ -45,7 +45,6 @@ import org.jboss.netty.channel.ReceiveBufferSizePredictor;
|
||||
import org.jboss.netty.channel.socket.nio.SocketSendBufferPool.SendBuffer;
|
||||
import org.jboss.netty.logging.InternalLogger;
|
||||
import org.jboss.netty.logging.InternalLoggerFactory;
|
||||
import org.jboss.netty.util.ThreadRenamingRunnable;
|
||||
import org.jboss.netty.util.internal.LinkedTransferQueue;
|
||||
|
||||
/**
|
||||
@ -168,9 +167,7 @@ class NioDatagramWorker implements Runnable {
|
||||
boolean success = false;
|
||||
try {
|
||||
// Start the main selector loop. See run() for details.
|
||||
executor.execute(new ThreadRenamingRunnable(
|
||||
this, "NewIO", "DatagramWorker",
|
||||
String.valueOf(bossId), String.valueOf(id), null));
|
||||
executor.execute(this);
|
||||
success = true;
|
||||
} finally {
|
||||
if (!success) {
|
||||
|
@ -39,7 +39,6 @@ import org.jboss.netty.channel.ChannelStateEvent;
|
||||
import org.jboss.netty.channel.MessageEvent;
|
||||
import org.jboss.netty.logging.InternalLogger;
|
||||
import org.jboss.netty.logging.InternalLoggerFactory;
|
||||
import org.jboss.netty.util.ThreadRenamingRunnable;
|
||||
import org.jboss.netty.util.internal.DeadLockProofWorker;
|
||||
|
||||
/**
|
||||
@ -154,12 +153,7 @@ class NioServerSocketPipelineSink extends AbstractChannelSink {
|
||||
|
||||
Executor bossExecutor =
|
||||
((NioServerSocketChannelFactory) channel.getFactory()).bossExecutor;
|
||||
DeadLockProofWorker.start(
|
||||
bossExecutor,
|
||||
new ThreadRenamingRunnable(
|
||||
new Boss(channel),
|
||||
"NewIO", "ServerBoss", null, String.valueOf(id),
|
||||
channel.toString()));
|
||||
DeadLockProofWorker.start(bossExecutor, new Boss(channel));
|
||||
bossStarted = true;
|
||||
} catch (Throwable t) {
|
||||
future.setFailure(t);
|
||||
|
@ -46,7 +46,6 @@ import org.jboss.netty.channel.ReceiveBufferSizePredictor;
|
||||
import org.jboss.netty.channel.socket.nio.SocketSendBufferPool.SendBuffer;
|
||||
import org.jboss.netty.logging.InternalLogger;
|
||||
import org.jboss.netty.logging.InternalLoggerFactory;
|
||||
import org.jboss.netty.util.ThreadRenamingRunnable;
|
||||
import org.jboss.netty.util.internal.DeadLockProofWorker;
|
||||
import org.jboss.netty.util.internal.LinkedTransferQueue;
|
||||
|
||||
@ -108,12 +107,7 @@ class NioWorker implements Runnable {
|
||||
// Start the worker thread with the new Selector.
|
||||
boolean success = false;
|
||||
try {
|
||||
DeadLockProofWorker.start(
|
||||
executor,
|
||||
new ThreadRenamingRunnable(
|
||||
this, "NewIO",
|
||||
server? "ServerWorker" : "ClientWorker",
|
||||
String.valueOf(bossId), String.valueOf(id), null));
|
||||
DeadLockProofWorker.start(executor, this);
|
||||
success = true;
|
||||
} finally {
|
||||
if (!success) {
|
||||
|
@ -30,7 +30,6 @@ import org.jboss.netty.channel.ChannelPipeline;
|
||||
import org.jboss.netty.channel.ChannelState;
|
||||
import org.jboss.netty.channel.ChannelStateEvent;
|
||||
import org.jboss.netty.channel.MessageEvent;
|
||||
import org.jboss.netty.util.ThreadRenamingRunnable;
|
||||
import org.jboss.netty.util.internal.DeadLockProofWorker;
|
||||
|
||||
/**
|
||||
@ -132,13 +131,7 @@ class OioClientSocketPipelineSink extends AbstractChannelSink {
|
||||
fireChannelConnected(channel, channel.getRemoteAddress());
|
||||
|
||||
// Start the business.
|
||||
DeadLockProofWorker.start(
|
||||
workerExecutor,
|
||||
new ThreadRenamingRunnable(
|
||||
new OioWorker(channel),
|
||||
"OldIO", "ClientWorker",
|
||||
String.valueOf(id), String.valueOf(channel.getId()),
|
||||
channel.toString()));
|
||||
DeadLockProofWorker.start(workerExecutor, new OioWorker(channel));
|
||||
workerStarted = true;
|
||||
} catch (Throwable t) {
|
||||
future.setFailure(t);
|
||||
|
@ -28,7 +28,6 @@ import org.jboss.netty.channel.ChannelPipeline;
|
||||
import org.jboss.netty.channel.ChannelState;
|
||||
import org.jboss.netty.channel.ChannelStateEvent;
|
||||
import org.jboss.netty.channel.MessageEvent;
|
||||
import org.jboss.netty.util.ThreadRenamingRunnable;
|
||||
import org.jboss.netty.util.internal.DeadLockProofWorker;
|
||||
|
||||
/**
|
||||
@ -105,11 +104,7 @@ class OioDatagramPipelineSink extends AbstractChannelSink {
|
||||
// Start the business.
|
||||
DeadLockProofWorker.start(
|
||||
workerExecutor,
|
||||
new ThreadRenamingRunnable(
|
||||
new OioDatagramWorker(channel),
|
||||
"OldIO", "DatagramWorker",
|
||||
String.valueOf(id), String.valueOf(channel.getId()),
|
||||
channel.toString()));
|
||||
new OioDatagramWorker(channel));
|
||||
workerStarted = true;
|
||||
} catch (Throwable t) {
|
||||
future.setFailure(t);
|
||||
@ -154,17 +149,9 @@ class OioDatagramPipelineSink extends AbstractChannelSink {
|
||||
// Start the business.
|
||||
DeadLockProofWorker.start(
|
||||
workerExecutor,
|
||||
new ThreadRenamingRunnable(
|
||||
new OioDatagramWorker(channel),
|
||||
service, category, String.valueOf(id),
|
||||
String.valueOf(channel.getId()), comment));
|
||||
new OioDatagramWorker(channel));
|
||||
} else {
|
||||
// Worker started by bind() - just rename.
|
||||
Thread workerThread = channel.workerThread;
|
||||
if (workerThread != null) {
|
||||
ThreadRenamingRunnable.renameThread(
|
||||
workerThread, service, category, String.valueOf(id), String.valueOf(channel.getId()), comment);
|
||||
}
|
||||
// Worker started by bind() - nothing to do.
|
||||
}
|
||||
|
||||
workerStarted = true;
|
||||
|
@ -27,7 +27,6 @@ import org.jboss.netty.buffer.ChannelBuffer;
|
||||
import org.jboss.netty.channel.Channel;
|
||||
import org.jboss.netty.channel.ChannelFuture;
|
||||
import org.jboss.netty.channel.ReceiveBufferSizePredictor;
|
||||
import org.jboss.netty.util.ThreadRenamingRunnable;
|
||||
|
||||
/**
|
||||
*
|
||||
@ -174,16 +173,6 @@ class OioDatagramWorker implements Runnable {
|
||||
channel.socket.disconnect();
|
||||
future.setSuccess();
|
||||
if (connected) {
|
||||
// Update the worker's thread name to reflect the state change.
|
||||
Thread workerThread = channel.workerThread;
|
||||
if (workerThread != null) {
|
||||
ThreadRenamingRunnable.renameThread(
|
||||
workerThread, "OldIO", "DatagramWorker",
|
||||
String.valueOf(((OioDatagramChannelFactory) channel.getFactory()).id),
|
||||
String.valueOf(channel.getId()),
|
||||
channel.toString());
|
||||
}
|
||||
|
||||
// Notify.
|
||||
fireChannelDisconnected(channel);
|
||||
}
|
||||
|
@ -34,7 +34,6 @@ import org.jboss.netty.channel.ChannelStateEvent;
|
||||
import org.jboss.netty.channel.MessageEvent;
|
||||
import org.jboss.netty.logging.InternalLogger;
|
||||
import org.jboss.netty.logging.InternalLoggerFactory;
|
||||
import org.jboss.netty.util.ThreadRenamingRunnable;
|
||||
import org.jboss.netty.util.internal.DeadLockProofWorker;
|
||||
|
||||
/**
|
||||
@ -148,11 +147,7 @@ class OioServerSocketPipelineSink extends AbstractChannelSink {
|
||||
|
||||
Executor bossExecutor =
|
||||
((OioServerSocketChannelFactory) channel.getFactory()).bossExecutor;
|
||||
DeadLockProofWorker.start(
|
||||
bossExecutor,
|
||||
new ThreadRenamingRunnable(
|
||||
new Boss(channel), "OldIO", "ServerBoss", null,
|
||||
String.valueOf(id), channel.toString()));
|
||||
DeadLockProofWorker.start(bossExecutor, new Boss(channel));
|
||||
bossStarted = true;
|
||||
} catch (Throwable t) {
|
||||
future.setFailure(t);
|
||||
@ -218,12 +213,7 @@ class OioServerSocketPipelineSink extends AbstractChannelSink {
|
||||
acceptedSocket);
|
||||
DeadLockProofWorker.start(
|
||||
workerExecutor,
|
||||
new ThreadRenamingRunnable(
|
||||
new OioWorker(acceptedChannel),
|
||||
"OldIO", "ServerWorker",
|
||||
String.valueOf(id),
|
||||
String.valueOf(acceptedChannel.getId()),
|
||||
acceptedChannel.toString()));
|
||||
new OioWorker(acceptedChannel));
|
||||
} catch (Exception e) {
|
||||
logger.warn(
|
||||
"Failed to initialize an accepted socket.", e);
|
||||
|
93
src/main/java/org/jboss/netty/util/NamedThreadFactory.java
Normal file
93
src/main/java/org/jboss/netty/util/NamedThreadFactory.java
Normal file
@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Copyright 2011 Red Hat, Inc.
|
||||
*
|
||||
* Red Hat 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.jboss.netty.util;
|
||||
|
||||
import org.jboss.netty.channel.ChannelFactory;
|
||||
import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
|
||||
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
/**
|
||||
* A {@link ThreadFactory} that creates a new {@link Thread} with the specified name and thread ID.
|
||||
* This class is useful when you want to customize the name of the I/O threads:
|
||||
* <pre>
|
||||
* {@link ChannelFactory} f = new {@link NioServerSocketChannelFactory}(
|
||||
* {@link Executors}.{@link Executors#newCachedThreadPool(java.util.concurrent.ThreadFactory) newCachedThreadPool}(new {@link NamedThreadFactory}("myServerBoss-")),
|
||||
* {@link Executors}.{@link Executors#newCachedThreadPool(java.util.concurrent.ThreadFactory) newCachedThreadPool}(new {@link NamedThreadFactory}("myServerWorker-")));
|
||||
* </pre>
|
||||
*
|
||||
* @author <a href="http://jboss.org/netty/">The Netty Project</a>
|
||||
* @author <a href="http://gleamynode.net/">Trustin Lee</a>
|
||||
*/
|
||||
public class NamedThreadFactory implements ThreadFactory {
|
||||
|
||||
private final ThreadGroup group;
|
||||
private final AtomicInteger threadId = new AtomicInteger(1);
|
||||
private final String prefix;
|
||||
private final boolean daemon;
|
||||
private final int priority;
|
||||
|
||||
/**
|
||||
* Creates a new factory that creates a {@link Thread} with the specified name prefix.
|
||||
*
|
||||
* @param prefix the prefix of the new thread's name
|
||||
*/
|
||||
public NamedThreadFactory(String prefix) {
|
||||
this(prefix, false, Thread.NORM_PRIORITY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new factory that creates a {@link Thread} with the specified name prefix.
|
||||
*
|
||||
* @param prefix the prefix of the new thread's name
|
||||
* @param daemon {@code true} if the new thread is a daemon thread
|
||||
* @param priority the priority of the new thread
|
||||
*/
|
||||
public NamedThreadFactory(String prefix, boolean daemon, int priority) {
|
||||
if (prefix == null) {
|
||||
throw new NullPointerException("prefix");
|
||||
}
|
||||
if (priority < Thread.MIN_PRIORITY || priority > Thread.MAX_PRIORITY) {
|
||||
throw new IllegalArgumentException(
|
||||
"priority: " + priority +
|
||||
" (expected: >= " + Thread.MIN_PRIORITY + " && <= " + Thread.MAX_PRIORITY + ')');
|
||||
}
|
||||
|
||||
this.prefix = prefix;
|
||||
this.daemon = daemon;
|
||||
this.priority = priority;
|
||||
|
||||
SecurityManager s = System.getSecurityManager();
|
||||
if (s != null) {
|
||||
group = s.getThreadGroup();
|
||||
} else {
|
||||
group = Thread.currentThread().getThreadGroup();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc} The name of the thread is {@code "prefix + threadId"}. (e.g. {@code "ioThread-1"} if
|
||||
* {@code prefix} is {@code "ioThread-"}.
|
||||
*/
|
||||
public Thread newThread(Runnable r) {
|
||||
Thread t = new Thread(group, r, prefix + threadId.getAndIncrement());
|
||||
t.setDaemon(daemon);
|
||||
t.setPriority(priority);
|
||||
return t;
|
||||
}
|
||||
}
|
@ -1,96 +0,0 @@
|
||||
/*
|
||||
* Copyright 2009 Red Hat, Inc.
|
||||
*
|
||||
* Red Hat 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.jboss.netty.util;
|
||||
|
||||
/**
|
||||
* Overrides the thread name proposed by {@link ThreadRenamingRunnable}.
|
||||
*
|
||||
* @author <a href="http://www.jboss.org/netty/">The Netty Project</a>
|
||||
* @author <a href="http://gleamynode.net/">Trustin Lee</a>
|
||||
* @version $Rev$, $Date$
|
||||
*/
|
||||
public interface ThreadNameDeterminer {
|
||||
|
||||
/**
|
||||
* The default {@link ThreadNameDeterminer} that generates a thread name
|
||||
* which contains all specified information.
|
||||
*/
|
||||
ThreadNameDeterminer PROPOSED = new ThreadNameDeterminer() {
|
||||
@Override
|
||||
public String determineThreadName(String current, String service,
|
||||
String category, String parentId, String id, String comment) throws Exception {
|
||||
|
||||
String newName =
|
||||
(format("", " ", service) +
|
||||
format("", " ", category) +
|
||||
format("#", " ", parentId, id) +
|
||||
format("(", ")", comment)).trim();
|
||||
if (newName.length() == 0) {
|
||||
return null;
|
||||
} else {
|
||||
return newName;
|
||||
}
|
||||
}
|
||||
|
||||
private String format(String prefix, String postfix, String... components) {
|
||||
StringBuilder buf = new StringBuilder();
|
||||
for (String c: components) {
|
||||
if (c.length() == 0) {
|
||||
continue;
|
||||
}
|
||||
buf.append(c);
|
||||
buf.append(':');
|
||||
}
|
||||
|
||||
if (buf.length() == 0) {
|
||||
return "";
|
||||
}
|
||||
|
||||
buf.setLength(buf.length() - 1); // Remove trailing ':'
|
||||
return prefix + buf + postfix;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* An alternative {@link ThreadNameDeterminer} that rejects the proposed
|
||||
* thread name and retains the current one.
|
||||
*/
|
||||
ThreadNameDeterminer CURRENT = new ThreadNameDeterminer() {
|
||||
@Override
|
||||
public String determineThreadName(String current, String service,
|
||||
String category, String parentId, String id, String comment) throws Exception {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Overrides the thread name proposed by {@link ThreadRenamingRunnable}.
|
||||
*
|
||||
* @param current the current thread name
|
||||
* @param service the service name (e.g. <tt>"NewIO"</tt> or <tt>"OldIO"</tt>)
|
||||
* @param category the category name (e.g. <tt>"ServerBoss"</tt> or <tt>"ClientWorker"</tt>)
|
||||
* @param parentId the parent thread ID (e.g. <tt>"1"</tt>)
|
||||
* @param id the thread ID (e.g. <tt>"3"</tt>)
|
||||
* @param comment the optional comment which might help debugging
|
||||
*
|
||||
* @return the actual new thread name.
|
||||
* If {@code null} is returned, the proposed thread name is
|
||||
* discarded (i.e. no rename).
|
||||
*/
|
||||
String determineThreadName(
|
||||
String current,
|
||||
String service, String category, String parentId, String id, String comment) throws Exception;
|
||||
}
|
@ -1,198 +0,0 @@
|
||||
/*
|
||||
* Copyright 2009 Red Hat, Inc.
|
||||
*
|
||||
* Red Hat 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.jboss.netty.util;
|
||||
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.jboss.netty.logging.InternalLogger;
|
||||
import org.jboss.netty.logging.InternalLoggerFactory;
|
||||
|
||||
|
||||
/**
|
||||
* A {@link Runnable} that changes the current thread name and reverts it back
|
||||
* when its execution ends. To change the default thread names set by Netty,
|
||||
* use {@link #setThreadNameDeterminer(ThreadNameDeterminer)}.
|
||||
*
|
||||
* @author <a href="http://www.jboss.org/netty/">The Netty Project</a>
|
||||
* @author <a href="http://gleamynode.net/">Trustin Lee</a>
|
||||
*
|
||||
* @version $Rev$, $Date$
|
||||
*
|
||||
* @apiviz.landmark
|
||||
* @apiviz.has org.jboss.netty.util.ThreadNameDeterminer oneway - -
|
||||
*
|
||||
*/
|
||||
public class ThreadRenamingRunnable implements Runnable {
|
||||
|
||||
private static final InternalLogger logger =
|
||||
InternalLoggerFactory.getInstance(ThreadRenamingRunnable.class);
|
||||
|
||||
private static final Pattern SERVICE_PATTERN = Pattern.compile("[a-zA-Z0-9]*");
|
||||
private static final Pattern CATEGORY_PATTERN = SERVICE_PATTERN;
|
||||
private static final Pattern ID_PATTERN = SERVICE_PATTERN;
|
||||
|
||||
private static volatile ThreadNameDeterminer threadNameDeterminer =
|
||||
ThreadNameDeterminer.PROPOSED;
|
||||
|
||||
/**
|
||||
* Returns the {@link ThreadNameDeterminer} which overrides the proposed
|
||||
* new thread name.
|
||||
*/
|
||||
public static ThreadNameDeterminer getThreadNameDeterminer() {
|
||||
return threadNameDeterminer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@link ThreadNameDeterminer} which overrides the proposed new
|
||||
* thread name. Please note that the specified {@link ThreadNameDeterminer}
|
||||
* affects only new {@link ThreadRenamingRunnable}s; the existing instances
|
||||
* are not affected at all. Therefore, you should make sure to call this
|
||||
* method at the earliest possible point (i.e. before any Netty worker
|
||||
* thread starts) for consistent thread naming. Otherwise, you might see
|
||||
* the default thread names and the new names appear at the same time in
|
||||
* the full thread dump.
|
||||
*/
|
||||
public static void setThreadNameDeterminer(ThreadNameDeterminer threadNameDeterminer) {
|
||||
if (threadNameDeterminer == null) {
|
||||
throw new NullPointerException("threadNameDeterminer");
|
||||
}
|
||||
ThreadRenamingRunnable.threadNameDeterminer = threadNameDeterminer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renames the specified thread.
|
||||
*
|
||||
* @return {@code true} if and only if the thread was renamed
|
||||
*/
|
||||
public static boolean renameThread(Thread thread, String service, String category, String parentId, String id, String comment) {
|
||||
if (thread == null) {
|
||||
throw new NullPointerException("thread");
|
||||
}
|
||||
|
||||
validateNameComponents(service, category, parentId, id);
|
||||
|
||||
// Normalize the parameters.
|
||||
service = service != null? service : "";
|
||||
category = category != null? category : "";
|
||||
parentId = parentId != null? parentId : "";
|
||||
id = id != null? id : "";
|
||||
comment = comment != null? comment : "";
|
||||
|
||||
// Get the old & new thread names.
|
||||
String oldThreadName = thread.getName();
|
||||
String newThreadName = null;
|
||||
try {
|
||||
newThreadName = getThreadNameDeterminer().determineThreadName(
|
||||
oldThreadName, service, category, parentId, id, comment);
|
||||
} catch (Throwable t) {
|
||||
logger.warn("Failed to determine the thread name", t);
|
||||
}
|
||||
if (newThreadName == null || newThreadName.length() == 0) {
|
||||
newThreadName = oldThreadName;
|
||||
}
|
||||
|
||||
// Change the thread name.
|
||||
boolean renamed = false;
|
||||
if (!oldThreadName.equals(newThreadName)) {
|
||||
try {
|
||||
//System.out.println(newThreadName);
|
||||
thread.setName(newThreadName);
|
||||
renamed = true;
|
||||
} catch (SecurityException e) {
|
||||
logger.debug(
|
||||
"Failed to rename a thread " +
|
||||
"due to security restriction.", e);
|
||||
}
|
||||
}
|
||||
|
||||
return renamed;
|
||||
}
|
||||
|
||||
private static void validateNameComponents(String service, String category, String parentId, String id) {
|
||||
if (service != null && !SERVICE_PATTERN.matcher(service).matches()) {
|
||||
throw new IllegalArgumentException(
|
||||
"service: " + service +
|
||||
" (expected: " + SERVICE_PATTERN.pattern() + ')');
|
||||
}
|
||||
|
||||
if (category != null && !CATEGORY_PATTERN.matcher(category).matches()) {
|
||||
throw new IllegalArgumentException(
|
||||
"category: " + category +
|
||||
" (expected: " + CATEGORY_PATTERN.pattern() + ')');
|
||||
}
|
||||
|
||||
if (parentId != null && !ID_PATTERN.matcher(parentId).matches()) {
|
||||
throw new IllegalArgumentException(
|
||||
"parentId: " + parentId +
|
||||
" (expected: " + ID_PATTERN.pattern() + ')');
|
||||
}
|
||||
|
||||
if (id != null && !ID_PATTERN.matcher(id).matches()) {
|
||||
throw new IllegalArgumentException(
|
||||
"id: " + id +
|
||||
" (expected: " + ID_PATTERN.pattern() + ')');
|
||||
}
|
||||
}
|
||||
|
||||
private final Runnable runnable;
|
||||
private final String service;
|
||||
private final String category;
|
||||
private final String parentId;
|
||||
private final String id;
|
||||
private final String comment;
|
||||
|
||||
/**
|
||||
* Creates a new instance which wraps the specified {@code runnable}
|
||||
* and changes the thread name to the specified thread name when the
|
||||
* specified {@code runnable} is running.
|
||||
*/
|
||||
public ThreadRenamingRunnable(
|
||||
Runnable runnable,
|
||||
String service, String category, String parentId, String id, String comment) {
|
||||
if (runnable == null) {
|
||||
throw new NullPointerException("runnable");
|
||||
}
|
||||
|
||||
validateNameComponents(service, category, parentId, id);
|
||||
this.runnable = runnable;
|
||||
this.service = service;
|
||||
this.category = category;
|
||||
this.parentId = parentId;
|
||||
this.id = id;
|
||||
this.comment = comment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
final Thread currentThread = Thread.currentThread();
|
||||
final String oldThreadName = currentThread.getName();
|
||||
|
||||
// Change the thread name before starting the actual runnable.
|
||||
final boolean renamed = renameThread(
|
||||
Thread.currentThread(), service, category, parentId, id, comment);
|
||||
|
||||
// Run the actual runnable and revert the name back when it ends.
|
||||
try {
|
||||
runnable.run();
|
||||
} finally {
|
||||
if (renamed) {
|
||||
// Revert the name back if the current thread was renamed.
|
||||
// We do not check the exception here because we know it works.
|
||||
currentThread.setName(oldThreadName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -23,7 +23,6 @@ import org.jboss.netty.channel.DefaultChannelPipeline;
|
||||
import org.jboss.netty.channel.SimpleChannelHandler;
|
||||
import org.jboss.netty.channel.StaticChannelPipeline;
|
||||
import org.jboss.netty.util.DebugUtil;
|
||||
import org.jboss.netty.util.ThreadRenamingRunnable;
|
||||
|
||||
/**
|
||||
* Simplifies an exception stack trace by removing unnecessary
|
||||
@ -42,14 +41,13 @@ public class StackTraceSimplifier {
|
||||
private static final Pattern EXCLUDED_STACK_TRACE =
|
||||
Pattern.compile(
|
||||
"^org\\.jboss\\.netty\\." +
|
||||
"(util\\.(ThreadRenamingRunnable|internal\\.DeadLockProofWorker)" +
|
||||
"(util\\.internal\\.DeadLockProofWorker" +
|
||||
"|channel\\.(SimpleChannel(Upstream|Downstream)?Handler|(Default|Static)ChannelPipeline.*))(\\$.*)?$");
|
||||
|
||||
/**
|
||||
* Removes unnecessary {@link StackTraceElement}s from the specified
|
||||
* exception. {@link ThreadRenamingRunnable}, {@link SimpleChannelHandler},
|
||||
* {@link DefaultChannelPipeline}, and {@link StaticChannelPipeline}
|
||||
* will be dropped from the trace.
|
||||
* exception. {@link SimpleChannelHandler}, {@link DefaultChannelPipeline},
|
||||
* and {@link StaticChannelPipeline} will be dropped from the trace.
|
||||
*/
|
||||
public static void simplify(Throwable e) {
|
||||
if (!SIMPLIFY_STACK_TRACE) {
|
||||
|
@ -1,133 +0,0 @@
|
||||
/*
|
||||
* Copyright 2009 Red Hat, Inc.
|
||||
*
|
||||
* Red Hat 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.jboss.netty.util;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.security.Permission;
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
|
||||
/**
|
||||
* @author <a href="http://www.jboss.org/netty/">The Netty Project</a>
|
||||
* @author <a href="http://gleamynode.net/">Trustin Lee</a>
|
||||
*
|
||||
* @version $Rev$, $Date$
|
||||
*
|
||||
*/
|
||||
public class ThreadRenamingRunnableTest {
|
||||
|
||||
@Test(expected = NullPointerException.class)
|
||||
public void shouldNotAllowNullRunnable() throws Exception {
|
||||
new ThreadRenamingRunnable(null, "a", "b", "c", "d", "e");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWithNulls() throws Exception {
|
||||
final String oldThreadName = Thread.currentThread().getName();
|
||||
Executor e = new ImmediateExecutor();
|
||||
e.execute(new ThreadRenamingRunnable(
|
||||
new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
assertEquals(oldThreadName, Thread.currentThread().getName());
|
||||
}
|
||||
}, null, null, null, null, null));
|
||||
|
||||
assertEquals(oldThreadName, Thread.currentThread().getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWithEmptyNames() throws Exception {
|
||||
final String oldThreadName = Thread.currentThread().getName();
|
||||
Executor e = new ImmediateExecutor();
|
||||
e.execute(new ThreadRenamingRunnable(
|
||||
new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
assertEquals(oldThreadName, Thread.currentThread().getName());
|
||||
}
|
||||
}, "", "", "", "", ""));
|
||||
|
||||
assertEquals(oldThreadName, Thread.currentThread().getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWithoutSecurityManager() throws Exception {
|
||||
final String oldThreadName = Thread.currentThread().getName();
|
||||
Executor e = new ImmediateExecutor();
|
||||
e.execute(new ThreadRenamingRunnable(
|
||||
new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
assertEquals("a b #c:d (e)", Thread.currentThread().getName());
|
||||
assertFalse(oldThreadName.equals(Thread.currentThread().getName()));
|
||||
}
|
||||
}, "a", "b", "c", "d", "e"));
|
||||
|
||||
assertEquals(oldThreadName, Thread.currentThread().getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWithSecurityManager() throws Exception {
|
||||
final String oldThreadName = Thread.currentThread().getName();
|
||||
Executor e = new ImmediateExecutor();
|
||||
System.setSecurityManager(new SecurityManager() {
|
||||
|
||||
@Override
|
||||
public void checkAccess(Thread t) {
|
||||
throw new SecurityException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkPermission(Permission perm, Object context) {
|
||||
// Allow
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkPermission(Permission perm) {
|
||||
// Allow
|
||||
}
|
||||
});
|
||||
try {
|
||||
e.execute(new ThreadRenamingRunnable(
|
||||
new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
assertEquals(oldThreadName, Thread.currentThread().getName());
|
||||
}
|
||||
}, "a", "b", "c", "d", "e"));
|
||||
} finally {
|
||||
System.setSecurityManager(null);
|
||||
assertEquals(oldThreadName, Thread.currentThread().getName());
|
||||
}
|
||||
}
|
||||
|
||||
private static class ImmediateExecutor implements Executor {
|
||||
|
||||
ImmediateExecutor() {
|
||||
super();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Runnable command) {
|
||||
command.run();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -23,7 +23,6 @@ import org.jboss.netty.buffer.ChannelBuffer;
|
||||
import org.jboss.netty.channel.Channel;
|
||||
import org.jboss.netty.channel.DefaultChannelPipeline;
|
||||
import org.jboss.netty.channel.SimpleChannelHandler;
|
||||
import org.jboss.netty.util.ThreadRenamingRunnable;
|
||||
import org.junit.Test;
|
||||
|
||||
|
||||
@ -43,7 +42,6 @@ public class StackTraceSimplifierTest {
|
||||
new StackTraceElement(ChannelBuffer.class.getName(), "a", null, 1),
|
||||
new StackTraceElement("com.example.Foo", "b", null, 1),
|
||||
new StackTraceElement(SimpleChannelHandler.class.getName(), "c", null, 1),
|
||||
new StackTraceElement(ThreadRenamingRunnable.class.getName(), "d", null, 1),
|
||||
});
|
||||
|
||||
StackTraceSimplifier.simplify(e);
|
||||
@ -62,7 +60,6 @@ public class StackTraceSimplifierTest {
|
||||
new StackTraceElement("com.example.Foo", "b", null, 1),
|
||||
new StackTraceElement(SimpleChannelHandler.class.getName(), "c", null, 1),
|
||||
new StackTraceElement(DefaultChannelPipeline.class.getName(), "d", null, 1),
|
||||
new StackTraceElement(ThreadRenamingRunnable.class.getName(), "e", null, 1),
|
||||
});
|
||||
|
||||
Exception e2 = new Exception(e1);
|
||||
@ -71,7 +68,6 @@ public class StackTraceSimplifierTest {
|
||||
new StackTraceElement("com.example.Bar", "b", null, 1),
|
||||
new StackTraceElement(SimpleChannelHandler.class.getName(), "c", null, 1),
|
||||
new StackTraceElement(DefaultChannelPipeline.class.getName(), "d", null, 1),
|
||||
new StackTraceElement(ThreadRenamingRunnable.class.getName(), "e", null, 1),
|
||||
});
|
||||
|
||||
StackTraceSimplifier.simplify(e2);
|
||||
@ -95,13 +91,15 @@ public class StackTraceSimplifierTest {
|
||||
new StackTraceElement(ChannelBuffer.class.getName(), "a", null, 1),
|
||||
new StackTraceElement("com.example.Foo", "b", null, 1),
|
||||
new StackTraceElement(SimpleChannelHandler.class.getName(), "c", null, 1),
|
||||
new StackTraceElement(ThreadRenamingRunnable.class.getName(), "d", null, 1),
|
||||
});
|
||||
|
||||
StackTraceSimplifier.simplify(e);
|
||||
|
||||
StackTraceElement[] simplified = e.getStackTrace();
|
||||
assertEquals(5, simplified.length);
|
||||
for (StackTraceElement ste: simplified) {
|
||||
System.out.println(ste);
|
||||
}
|
||||
assertEquals(4, simplified.length);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
Loading…
Reference in New Issue
Block a user