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]