Author: costin Date: Fri Nov 25 21:39:20 2005 New Revision: 349082 URL: http://svn.apache.org/viewcvs?rev=349082&view=rev Log: Add threads ( without Reaper and Expirer, not used or needed )
Added: tomcat/sandbox/java/org/apache/tomcat/util/threads/ tomcat/sandbox/java/org/apache/tomcat/util/threads/ThreadPool.java tomcat/sandbox/java/org/apache/tomcat/util/threads/ThreadPoolRunnable.java tomcat/sandbox/java/org/apache/tomcat/util/threads/ThreadWithAttributes.java tomcat/sandbox/java/org/apache/tomcat/util/threads/res/ tomcat/sandbox/java/org/apache/tomcat/util/threads/res/LocalStrings.properties tomcat/sandbox/java/org/apache/tomcat/util/threads/res/LocalStrings_es.properties tomcat/sandbox/java/org/apache/tomcat/util/threads/res/LocalStrings_fr.properties tomcat/sandbox/java/org/apache/tomcat/util/threads/res/LocalStrings_ja.properties Added: tomcat/sandbox/java/org/apache/tomcat/util/threads/ThreadPool.java URL: http://svn.apache.org/viewcvs/tomcat/sandbox/java/org/apache/tomcat/util/threads/ThreadPool.java?rev=349082&view=auto ============================================================================== --- tomcat/sandbox/java/org/apache/tomcat/util/threads/ThreadPool.java (added) +++ tomcat/sandbox/java/org/apache/tomcat/util/threads/ThreadPool.java Fri Nov 25 21:39:20 2005 @@ -0,0 +1,838 @@ +/* + * Copyright 1999-2005 The Apache Software Foundation + * + * Licensed 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.tomcat.util.threads; + +import java.util.*; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.tomcat.util.res.StringManager; + +/** + * A thread pool that is trying to copy the apache process management. + * + * Should we remove this in favor of Doug Lea's thread package? + * + * @author Gal Shachor + * @author Yoav Shapira <[EMAIL PROTECTED]> + */ +public class ThreadPool { + + private static Log log = LogFactory.getLog(ThreadPool.class); + + private static StringManager sm = + StringManager.getManager("org.apache.tomcat.util.threads.res"); + + private static boolean logfull=true; + + /* + * Default values ... + */ + public static final int MAX_THREADS = 200; + public static final int MAX_THREADS_MIN = 10; + public static final int MAX_SPARE_THREADS = 50; + public static final int MIN_SPARE_THREADS = 4; + public static final int WORK_WAIT_TIMEOUT = 60*1000; + + /* + * Where the threads are held. + */ + protected ControlRunnable[] pool = null; + + /* + * A monitor thread that monitors the pool for idel threads. + */ + protected MonitorRunnable monitor; + + + /* + * Max number of threads that you can open in the pool. + */ + protected int maxThreads; + + /* + * Min number of idel threads that you can leave in the pool. + */ + protected int minSpareThreads; + + /* + * Max number of idel threads that you can leave in the pool. + */ + protected int maxSpareThreads; + + /* + * Number of threads in the pool. + */ + protected int currentThreadCount; + + /* + * Number of busy threads in the pool. + */ + protected int currentThreadsBusy; + + /* + * Flag that the pool should terminate all the threads and stop. + */ + protected boolean stopThePool; + + /* Flag to control if the main thread is 'daemon' */ + protected boolean isDaemon=true; + + /** The threads that are part of the pool. + * Key is Thread, value is the ControlRunnable + */ + protected Hashtable threads=new Hashtable(); + + protected Vector listeners=new Vector(); + + /** Name of the threadpool + */ + protected String name = "TP"; + + /** + * Sequence. + */ + protected int sequence = 1; + + /** + * Thread priority. + */ + protected int threadPriority = Thread.NORM_PRIORITY; + + + /** + * Constructor. + */ + public ThreadPool() { + maxThreads = MAX_THREADS; + maxSpareThreads = MAX_SPARE_THREADS; + minSpareThreads = MIN_SPARE_THREADS; + currentThreadCount = 0; + currentThreadsBusy = 0; + stopThePool = false; + } + + + /** Create a ThreadPool instance. + * + * @param jmx UNUSED + * @return ThreadPool instance. If JMX support is requested, you need to + * call register() in order to set a name. + */ + public static ThreadPool createThreadPool(boolean jmx) { + return new ThreadPool(); + } + + public synchronized void start() { + stopThePool=false; + currentThreadCount = 0; + currentThreadsBusy = 0; + + adjustLimits(); + + pool = new ControlRunnable[maxThreads]; + + openThreads(minSpareThreads); + if (maxSpareThreads < maxThreads) { + monitor = new MonitorRunnable(this); + } + } + + public MonitorRunnable getMonitor() { + return monitor; + } + + /** + * Sets the thread priority for current + * and future threads in this pool. + * + * @param threadPriority The new priority + * @throws IllegalArgumentException If the specified + * priority is less than Thread.MIN_PRIORITY or + * more than Thread.MAX_PRIORITY + */ + public synchronized void setThreadPriority(int threadPriority) { + if(log.isDebugEnabled()) + log.debug(getClass().getName() + + ": setPriority(" + threadPriority + "): here."); + + if (threadPriority < Thread.MIN_PRIORITY) { + throw new IllegalArgumentException("new priority < MIN_PRIORITY"); + } else if (threadPriority > Thread.MAX_PRIORITY) { + throw new IllegalArgumentException("new priority > MAX_PRIORITY"); + } + + // Set for future threads + this.threadPriority = threadPriority; + + Enumeration currentThreads = getThreads(); + Thread t = null; + while(currentThreads.hasMoreElements()) { + t = (Thread) currentThreads.nextElement(); + t.setPriority(threadPriority); + } + } + + /** + * Returns the priority level of current and + * future threads in this pool. + * + * @return The priority + */ + public int getThreadPriority() { + return threadPriority; + } + + + public void setMaxThreads(int maxThreads) { + this.maxThreads = maxThreads; + } + + public int getMaxThreads() { + return maxThreads; + } + + public void setMinSpareThreads(int minSpareThreads) { + this.minSpareThreads = minSpareThreads; + } + + public int getMinSpareThreads() { + return minSpareThreads; + } + + public void setMaxSpareThreads(int maxSpareThreads) { + this.maxSpareThreads = maxSpareThreads; + } + + public int getMaxSpareThreads() { + return maxSpareThreads; + } + + public int getCurrentThreadCount() { + return currentThreadCount; + } + + public int getCurrentThreadsBusy() { + return currentThreadsBusy; + } + + public boolean isDaemon() { + return isDaemon; + } + + public static int getDebug() { + return 0; + } + + /** The default is true - the created threads will be + * in daemon mode. If set to false, the control thread + * will not be daemon - and will keep the process alive. + */ + public void setDaemon( boolean b ) { + isDaemon=b; + } + + public boolean getDaemon() { + return isDaemon; + } + + public void setName(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + public int getSequence() { + return sequence++; + } + + public void addThread( Thread t, ControlRunnable cr ) { + threads.put( t, cr ); + for( int i=0; i<listeners.size(); i++ ) { + ThreadPoolListener tpl=(ThreadPoolListener)listeners.elementAt(i); + tpl.threadStart(this, t); + } + } + + public void removeThread( Thread t ) { + threads.remove(t); + for( int i=0; i<listeners.size(); i++ ) { + ThreadPoolListener tpl=(ThreadPoolListener)listeners.elementAt(i); + tpl.threadEnd(this, t); + } + } + + public void addThreadPoolListener( ThreadPoolListener tpl ) { + listeners.addElement( tpl ); + } + + public Enumeration getThreads(){ + return threads.keys(); + } + + public void run(Runnable r) { + ControlRunnable c = findControlRunnable(); + c.runIt(r); + } + + // + // You may wonder what you see here ... basically I am trying + // to maintain a stack of threads. This way locality in time + // is kept and there is a better chance to find residues of the + // thread in memory next time it runs. + // + + /** + * Executes a given Runnable on a thread in the pool, block if needed. + */ + public void runIt(ThreadPoolRunnable r) { + if(null == r) { + throw new NullPointerException(); + } + + ControlRunnable c = findControlRunnable(); + c.runIt(r); + } + + private ControlRunnable findControlRunnable() { + ControlRunnable c=null; + + if ( stopThePool ) { + throw new IllegalStateException(); + } + + // Obtain a free thread from the pool. + synchronized(this) { + + while (currentThreadsBusy == currentThreadCount) { + // All threads are busy + if (currentThreadCount < maxThreads) { + // Not all threads were open, + // Open new threads up to the max number of idel threads + int toOpen = currentThreadCount + minSpareThreads; + openThreads(toOpen); + } else { + logFull(log, currentThreadCount, maxThreads); + // Wait for a thread to become idel. + try { + this.wait(); + } + // was just catch Throwable -- but no other + // exceptions can be thrown by wait, right? + // So we catch and ignore this one, since + // it'll never actually happen, since nowhere + // do we say pool.interrupt(). + catch(InterruptedException e) { + log.error("Unexpected exception", e); + } + if( log.isDebugEnabled() ) { + log.debug("Finished waiting: CTC="+currentThreadCount + + ", CTB=" + currentThreadsBusy); + } + // Pool was stopped. Get away of the pool. + if( stopThePool) { + break; + } + } + } + // Pool was stopped. Get away of the pool. + if(0 == currentThreadCount || stopThePool) { + throw new IllegalStateException(); + } + + // If we are here it means that there is a free thread. Take it. + int pos = currentThreadCount - currentThreadsBusy - 1; + c = pool[pos]; + pool[pos] = null; + currentThreadsBusy++; + + } + return c; + } + + private static void logFull(Log loghelper, int currentThreadCount, + int maxThreads) { + if( logfull ) { + log.error(sm.getString("threadpool.busy", + new Integer(currentThreadCount), + new Integer(maxThreads))); + logfull=false; + } else if( log.isDebugEnabled() ) { + log.debug("All threads are busy " + currentThreadCount + " " + + maxThreads ); + } + } + + /** + * Stop the thread pool + */ + public synchronized void shutdown() { + if(!stopThePool) { + stopThePool = true; + if (monitor != null) { + monitor.terminate(); + monitor = null; + } + for(int i = 0; i < currentThreadCount - currentThreadsBusy; i++) { + try { + pool[i].terminate(); + } catch(Throwable t) { + /* + * Do nothing... The show must go on, we are shutting + * down the pool and nothing should stop that. + */ + log.error("Ignored exception while shutting down thread pool", t); + } + } + currentThreadsBusy = currentThreadCount = 0; + pool = null; + notifyAll(); + } + } + + /** + * Called by the monitor thread to harvest idle threads. + */ + protected synchronized void checkSpareControllers() { + + if(stopThePool) { + return; + } + + if((currentThreadCount - currentThreadsBusy) > maxSpareThreads) { + int toFree = currentThreadCount - + currentThreadsBusy - + maxSpareThreads; + + for(int i = 0 ; i < toFree ; i++) { + ControlRunnable c = pool[currentThreadCount - currentThreadsBusy - 1]; + c.terminate(); + pool[currentThreadCount - currentThreadsBusy - 1] = null; + currentThreadCount --; + } + + } + + } + + /** + * Returns the thread to the pool. + * Called by threads as they are becoming idel. + */ + protected synchronized void returnController(ControlRunnable c) { + + if(0 == currentThreadCount || stopThePool) { + c.terminate(); + return; + } + + // atomic + currentThreadsBusy--; + + pool[currentThreadCount - currentThreadsBusy - 1] = c; + notify(); + } + + /** + * Inform the pool that the specific thread finish. + * + * Called by the ControlRunnable.run() when the runnable + * throws an exception. + */ + protected synchronized void notifyThreadEnd(ControlRunnable c) { + currentThreadsBusy--; + currentThreadCount --; + notify(); + } + + + /* + * Checks for problematic configuration and fix it. + * The fix provides reasonable settings for a single CPU + * with medium load. + */ + protected void adjustLimits() { + if(maxThreads <= 0) { + maxThreads = MAX_THREADS; + } else if (maxThreads < MAX_THREADS_MIN) { + log.warn(sm.getString("threadpool.max_threads_too_low", + new Integer(maxThreads), + new Integer(MAX_THREADS_MIN))); + maxThreads = MAX_THREADS_MIN; + } + + if(maxSpareThreads >= maxThreads) { + maxSpareThreads = maxThreads; + } + + if(maxSpareThreads <= 0) { + if(1 == maxThreads) { + maxSpareThreads = 1; + } else { + maxSpareThreads = maxThreads/2; + } + } + + if(minSpareThreads > maxSpareThreads) { + minSpareThreads = maxSpareThreads; + } + + if(minSpareThreads <= 0) { + if(1 == maxSpareThreads) { + minSpareThreads = 1; + } else { + minSpareThreads = maxSpareThreads/2; + } + } + } + + /** Create missing threads. + * + * @param toOpen Total number of threads we'll have open + */ + protected void openThreads(int toOpen) { + + if(toOpen > maxThreads) { + toOpen = maxThreads; + } + + for(int i = currentThreadCount ; i < toOpen ; i++) { + pool[i - currentThreadsBusy] = new ControlRunnable(this); + } + + currentThreadCount = toOpen; + } + + /** @deprecated */ + void log( String s ) { + log.info(s); + //loghelper.flush(); + } + + /** + * Periodically execute an action - cleanup in this case + */ + public static class MonitorRunnable implements Runnable { + ThreadPool p; + Thread t; + int interval=WORK_WAIT_TIMEOUT; + boolean shouldTerminate; + + MonitorRunnable(ThreadPool p) { + this.p=p; + this.start(); + } + + public void start() { + shouldTerminate = false; + t = new Thread(this); + t.setDaemon(p.getDaemon() ); + t.setName(p.getName() + "-Monitor"); + t.start(); + } + + public void setInterval(int i ) { + this.interval=i; + } + + public void run() { + while(true) { + try { + + // Sleep for a while. + synchronized(this) { + this.wait(interval); + } + + // Check if should terminate. + // termination happens when the pool is shutting down. + if(shouldTerminate) { + break; + } + + // Harvest idle threads. + p.checkSpareControllers(); + + } catch(Throwable t) { + ThreadPool.log.error("Unexpected exception", t); + } + } + } + + public void stop() { + this.terminate(); + } + + /** Stop the monitor + */ + public synchronized void terminate() { + shouldTerminate = true; + this.notify(); + } + } + + /** + * A Thread object that executes various actions ( ThreadPoolRunnable ) + * under control of ThreadPool + */ + public static class ControlRunnable implements Runnable { + /** + * ThreadPool where this thread will be returned + */ + private ThreadPool p; + + /** + * The thread that executes the actions + */ + private ThreadWithAttributes t; + + /** + * The method that is executed in this thread + */ + + private ThreadPoolRunnable toRun; + private Runnable toRunRunnable; + + /** + * Stop this thread + */ + private boolean shouldTerminate; + + /** + * Activate the execution of the action + */ + private boolean shouldRun; + + /** + * Per thread data - can be used only if all actions are + * of the same type. + * A better mechanism is possible ( that would allow association of + * thread data with action type ), but right now it's enough. + */ + private boolean noThData; + + /** + * Start a new thread, with no method in it + */ + ControlRunnable(ThreadPool p) { + toRun = null; + shouldTerminate = false; + shouldRun = false; + this.p = p; + t = new ThreadWithAttributes(p, this); + t.setDaemon(true); + t.setName(p.getName() + "-Processor" + p.getSequence()); + t.setPriority(p.getThreadPriority()); + p.addThread( t, this ); + noThData=true; + t.start(); + } + + public void run() { + boolean _shouldRun = false; + boolean _shouldTerminate = false; + ThreadPoolRunnable _toRun = null; + try { + while (true) { + try { + /* Wait for work. */ + synchronized (this) { + while (!shouldRun && !shouldTerminate) { + this.wait(); + } + _shouldRun = shouldRun; + _shouldTerminate = shouldTerminate; + _toRun = toRun; + } + + if (_shouldTerminate) { + if (ThreadPool.log.isDebugEnabled()) + ThreadPool.log.debug("Terminate"); + break; + } + + /* Check if should execute a runnable. */ + try { + if (noThData) { + if (_toRun != null) { + Object thData[] = _toRun.getInitData(); + t.setThreadData(p, thData); + if (ThreadPool.log.isDebugEnabled()) + ThreadPool.log.debug( + "Getting new thread data"); + } + noThData = false; + } + + if (_shouldRun) { + if (_toRun != null) { + _toRun.runIt(t.getThreadData(p)); + } else if (toRunRunnable != null) { + toRunRunnable.run(); + } else { + if (ThreadPool.log.isDebugEnabled()) + ThreadPool.log.debug("No toRun ???"); + } + } + } catch (Throwable t) { + ThreadPool.log.error(sm.getString + ("threadpool.thread_error", t, toRun.toString())); + /* + * The runnable throw an exception (can be even a ThreadDeath), + * signalling that the thread die. + * + * The meaning is that we should release the thread from + * the pool. + */ + _shouldTerminate = true; + _shouldRun = false; + p.notifyThreadEnd(this); + } finally { + if (_shouldRun) { + shouldRun = false; + /* + * Notify the pool that the thread is now idle. + */ + p.returnController(this); + } + } + + /* + * Check if should terminate. + * termination happens when the pool is shutting down. + */ + if (_shouldTerminate) { + break; + } + } catch (InterruptedException ie) { /* for the wait operation */ + // can never happen, since we don't call interrupt + ThreadPool.log.error("Unexpected exception", ie); + } + } + } finally { + p.removeThread(Thread.currentThread()); + } + } + /** Run a task + * + * @param toRun + */ + public synchronized void runIt(Runnable toRun) { + this.toRunRunnable = toRun; + // Do not re-init, the whole idea is to run init only once per + // thread - the pool is supposed to run a single task, that is + // initialized once. + // noThData = true; + shouldRun = true; + this.notify(); + } + + /** Run a task + * + * @param toRun + */ + public synchronized void runIt(ThreadPoolRunnable toRun) { + this.toRun = toRun; + // Do not re-init, the whole idea is to run init only once per + // thread - the pool is supposed to run a single task, that is + // initialized once. + // noThData = true; + shouldRun = true; + this.notify(); + } + + public void stop() { + this.terminate(); + } + + public void kill() { + t.stop(); + } + + public synchronized void terminate() { + shouldTerminate = true; + this.notify(); + } + } + + /** + * Debug display of the stage of each thread. The return is html style, + * for display in the console ( it can be easily parsed too ). + * + * @return The thread status display + */ + public String threadStatusString() { + StringBuffer sb=new StringBuffer(); + Iterator it=threads.keySet().iterator(); + sb.append("<ul>"); + while( it.hasNext()) { + sb.append("<li>"); + ThreadWithAttributes twa=(ThreadWithAttributes) + it.next(); + sb.append(twa.getCurrentStage(this) ).append(" "); + sb.append( twa.getParam(this)); + sb.append( "</li>\n"); + } + sb.append("</ul>"); + return sb.toString(); + } + + /** Return an array with the status of each thread. The status + * indicates the current request processing stage ( for tomcat ) or + * whatever the thread is doing ( if the application using TP provide + * this info ) + * + * @return The status of all threads + */ + public String[] getThreadStatus() { + String status[]=new String[ threads.size()]; + Iterator it=threads.keySet().iterator(); + for( int i=0; ( i<status.length && it.hasNext()); i++ ) { + ThreadWithAttributes twa=(ThreadWithAttributes) + it.next(); + status[i]=twa.getCurrentStage(this); + } + return status; + } + + /** Return an array with the current "param" ( XXX better name ? ) + * of each thread. This is typically the last request. + * + * @return The params of all threads + */ + public String[] getThreadParam() { + String status[]=new String[ threads.size()]; + Iterator it=threads.keySet().iterator(); + for( int i=0; ( i<status.length && it.hasNext()); i++ ) { + ThreadWithAttributes twa=(ThreadWithAttributes) + it.next(); + Object o=twa.getParam(this); + status[i]=(o==null)? null : o.toString(); + } + return status; + } + + /** Interface to allow applications to be notified when + * a threads are created and stopped. + */ + public static interface ThreadPoolListener { + public void threadStart( ThreadPool tp, Thread t); + + public void threadEnd( ThreadPool tp, Thread t); + } +} Added: tomcat/sandbox/java/org/apache/tomcat/util/threads/ThreadPoolRunnable.java URL: http://svn.apache.org/viewcvs/tomcat/sandbox/java/org/apache/tomcat/util/threads/ThreadPoolRunnable.java?rev=349082&view=auto ============================================================================== --- tomcat/sandbox/java/org/apache/tomcat/util/threads/ThreadPoolRunnable.java (added) +++ tomcat/sandbox/java/org/apache/tomcat/util/threads/ThreadPoolRunnable.java Fri Nov 25 21:39:20 2005 @@ -0,0 +1,38 @@ +/* + * Copyright 1999-2004 The Apache Software Foundation + * + * Licensed 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.tomcat.util.threads; + + +/** Implemented if you want to run a piece of code inside a thread pool. + */ +public interface ThreadPoolRunnable { + // XXX use notes or a hashtable-like + // Important: ThreadData in JDK1.2 is implemented as a Hashtable( Thread -> object ), + // expensive. + + /** Called when this object is first loaded in the thread pool. + * Important: all workers in a pool must be of the same type, + * otherwise the mechanism becomes more complex. + */ + public Object[] getInitData(); + + /** This method will be executed in one of the pool's threads. The + * thread will be returned to the pool. + */ + public void runIt(Object thData[]); + +} Added: tomcat/sandbox/java/org/apache/tomcat/util/threads/ThreadWithAttributes.java URL: http://svn.apache.org/viewcvs/tomcat/sandbox/java/org/apache/tomcat/util/threads/ThreadWithAttributes.java?rev=349082&view=auto ============================================================================== --- tomcat/sandbox/java/org/apache/tomcat/util/threads/ThreadWithAttributes.java (added) +++ tomcat/sandbox/java/org/apache/tomcat/util/threads/ThreadWithAttributes.java Fri Nov 25 21:39:20 2005 @@ -0,0 +1,100 @@ +/* + * Copyright 1999-2004 The Apache Software Foundation + * + * Licensed 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.tomcat.util.threads; + +import java.util.Hashtable; + +/** Special thread that allows storing of attributes and notes. + * A guard is used to prevent untrusted code from accessing the + * attributes. + * + * This avoids hash lookups and provide something very similar + * with ThreadLocal ( but compatible with JDK1.1 and faster on + * JDK < 1.4 ). + * + * The main use is to store 'state' for monitoring ( like "processing + * request 'GET /' "). + */ +public class ThreadWithAttributes extends Thread { + + private Object control; + public static int MAX_NOTES=16; + private Object notes[]=new Object[MAX_NOTES]; + private Hashtable attributes=new Hashtable(); + private String currentStage; + private Object param; + + private Object thData[]; + + public ThreadWithAttributes(Object control, Runnable r) { + super(r); + this.control=control; + } + + public final Object[] getThreadData(Object control ) { + return thData; + } + + public final void setThreadData(Object control, Object thData[] ) { + this.thData=thData; + } + + /** Notes - for attributes that need fast access ( array ) + * The application is responsible for id management + */ + public final void setNote( Object control, int id, Object value ) { + if( this.control != control ) return; + notes[id]=value; + } + + /** Information about the curent performed operation + */ + public final String getCurrentStage(Object control) { + if( this.control != control ) return null; + return currentStage; + } + + /** Information about the current request ( or the main object + * we are processing ) + */ + public final Object getParam(Object control) { + if( this.control != control ) return null; + return param; + } + + public final void setCurrentStage(Object control, String currentStage) { + if( this.control != control ) return; + this.currentStage = currentStage; + } + + public final void setParam( Object control, Object param ) { + if( this.control != control ) return; + this.param=param; + } + + public final Object getNote(Object control, int id ) { + if( this.control != control ) return null; + return notes[id]; + } + + /** Generic attributes. You'll need a hashtable lookup - + * you can use notes for array access. + */ + public final Hashtable getAttributes(Object control) { + return attributes; + } +} Added: tomcat/sandbox/java/org/apache/tomcat/util/threads/res/LocalStrings.properties URL: http://svn.apache.org/viewcvs/tomcat/sandbox/java/org/apache/tomcat/util/threads/res/LocalStrings.properties?rev=349082&view=auto ============================================================================== --- tomcat/sandbox/java/org/apache/tomcat/util/threads/res/LocalStrings.properties (added) +++ tomcat/sandbox/java/org/apache/tomcat/util/threads/res/LocalStrings.properties Fri Nov 25 21:39:20 2005 @@ -0,0 +1,3 @@ +threadpool.busy=All threads ({0}) are currently busy, waiting. Increase maxThreads ({1}) or check the servlet status +threadpool.max_threads_too_low=maxThreads setting ({0}) too low, set to {1} +threadpool.thread_error=Caught exception ({0}) executing {1}, terminating thread Added: tomcat/sandbox/java/org/apache/tomcat/util/threads/res/LocalStrings_es.properties URL: http://svn.apache.org/viewcvs/tomcat/sandbox/java/org/apache/tomcat/util/threads/res/LocalStrings_es.properties?rev=349082&view=auto ============================================================================== --- tomcat/sandbox/java/org/apache/tomcat/util/threads/res/LocalStrings_es.properties (added) +++ tomcat/sandbox/java/org/apache/tomcat/util/threads/res/LocalStrings_es.properties Fri Nov 25 21:39:20 2005 @@ -0,0 +1,3 @@ +threadpool.busy=Todos los hilos ({0}) están ahora ocupados, esperando. Incremente maxThreads ({1}) o revise el estado del servlet +threadpool.max_threads_too_low=valor de maxThreads ({0}) demasiado bajo, puesto a {1} +threadpool.thread_error=Cogida excepción ({0}) ejecutando {1}, terminando hilo Added: tomcat/sandbox/java/org/apache/tomcat/util/threads/res/LocalStrings_fr.properties URL: http://svn.apache.org/viewcvs/tomcat/sandbox/java/org/apache/tomcat/util/threads/res/LocalStrings_fr.properties?rev=349082&view=auto ============================================================================== --- tomcat/sandbox/java/org/apache/tomcat/util/threads/res/LocalStrings_fr.properties (added) +++ tomcat/sandbox/java/org/apache/tomcat/util/threads/res/LocalStrings_fr.properties Fri Nov 25 21:39:20 2005 @@ -0,0 +1,3 @@ +threadpool.busy=Tous les threads ({0}) sont actuellement occupés, attente. Augmentez maxThreads ({1}) ou vérifiez le servlet status +threadpool.max_threads_too_low=le réglage maxThreads ({0}) est trop bas, mis à {1} +threadpool.thread_error=Réception d''une exception ({0}) en exécutant {1}, arrêt du thread Added: tomcat/sandbox/java/org/apache/tomcat/util/threads/res/LocalStrings_ja.properties URL: http://svn.apache.org/viewcvs/tomcat/sandbox/java/org/apache/tomcat/util/threads/res/LocalStrings_ja.properties?rev=349082&view=auto ============================================================================== --- tomcat/sandbox/java/org/apache/tomcat/util/threads/res/LocalStrings_ja.properties (added) +++ tomcat/sandbox/java/org/apache/tomcat/util/threads/res/LocalStrings_ja.properties Fri Nov 25 21:39:20 2005 @@ -0,0 +1,3 @@ +threadpool.busy=\u3059\u3079\u3066\u306e\u30b9\u30ec\u30c3\u30c9 ({0}) \u304c\u73fe\u5728\u7a3c\u50cd\u4e2d\u3067\u5f85\u6a5f\u3057\u3066\u3044\u307e\u3059\u3002maxThreads ({1}) \u3092\u5897\u3084\u3059\u304b\u3001\u305d\u306e\u30b5\u30fc\u30d6\u30ec\u30c3\u30c8\u306e\u30b9\u30c6\u30fc\u30bf\u30b9\u3092\u30c1\u30a7\u30c3\u30af\u3057\u3066\u304f\u3060\u3055\u3044 +threadpool.max_threads_too_low=maxThreads\u306e\u8a2d\u5b9a ({0}) \u304c\u5c0f\u3055\u3059\u304e\u308b\u306e\u3067\u3001{1}\u306b\u8a2d\u5b9a\u3057\u3066\u304f\u3060\u3055\u3044 +threadpool.thread_error={1} \u3092\u5b9f\u884c\u4e2d\u306b\u4f8b\u5916 ({0}) \u3092\u30ad\u30e3\u30c3\u30c1\u3057\u305f\u306e\u3067\u3001\u30b9\u30ec\u30c3\u30c9\u3092\u7d42\u4e86\u3057\u307e\u3059 --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]