| /* |
| * This file is part of the QuickServer library |
| * Copyright (C) QuickServer.org |
| * |
| * Use, modification, copying and distribution of this software is subject to |
| * the terms and conditions of the GNU Lesser General Public License. |
| * You should have received a copy of the GNU LGP License along with this |
| * library; if not, you can download a copy from <http://www.quickserver.org/>. |
| * |
| * For questions, suggestions, bug-reports, enhancement-requests etc. |
| * visit http://www.quickserver.org |
| * |
| */ |
| |
| package org.quickserver.util.pool.thread; |
| |
| import java.util.*; |
| import org.quickserver.util.pool.*; |
| import org.apache.commons.pool.*; |
| import org.quickserver.net.server.*; |
| import org.quickserver.util.xmlreader.PoolConfig; |
| import java.util.logging.*; |
| |
| /** |
| * This is a class for managing the pool of threads for |
| * handling clients. |
| * @author Akshathkumar Shetty |
| * @since 1.3 |
| */ |
| public class ClientPool { |
| private static final Logger logger = Logger.getLogger(ClientPool.class.getName()); |
| |
| protected List clients = new ArrayList(3); |
| protected ObjectPool pool; |
| protected PoolConfig poolConfig; |
| private int countNioWriteThreads; //v1.4.6 |
| private int maxThreadsForNioWrite = 10; |
| |
| public ClientPool(QSObjectPool objectPool, PoolConfig poolConfig) { |
| this.poolConfig = poolConfig; |
| pool = objectPool; |
| } |
| |
| public ObjectPool getObjectPool() { |
| return pool; |
| } |
| |
| public void addClient(Runnable r) throws NoSuchElementException { |
| addClient(r, false); |
| } |
| |
| public void addClient(Runnable r, boolean keepObjOnFail) |
| throws NoSuchElementException { |
| //logger.finest("Adding Runnable: "+r); |
| ClientThread ct = null; |
| synchronized(this) { |
| clients.add(r); |
| |
| try { |
| ct = (ClientThread)pool.borrowObject(); |
| if(ct.isReady()==false) { |
| //ct.start(); |
| wait(500); //timeout was just in case :-) |
| //Thread.yield(); |
| } |
| |
| } catch(NoSuchElementException e) { |
| logger.info("No free threads: "+e); |
| if(keepObjOnFail==false) { |
| clients.remove(r); |
| } |
| throw e; |
| } catch(Exception e) { |
| logger.warning("Error in addClient: "+e+", Closing client: "+(ClientHandler)r); |
| try { |
| ((ClientHandler)r).forceClose(); |
| } catch(Exception er) { |
| logger.warning("Error closing client: "+er); |
| } |
| try { |
| if(ct!=null) pool.returnObject(ct); |
| } catch(Exception er) { |
| logger.warning("Error in returning thread: "+er); |
| } |
| } |
| } |
| |
| synchronized(ct) { |
| ct.notify(); |
| } |
| } |
| |
| public synchronized void returnObject(Object object) { |
| try { |
| pool.returnObject(object); |
| } catch(Exception e) { |
| logger.warning("IGONRED: Error while returning object : "+e); |
| ((Thread)object).interrupt(); |
| } |
| } |
| |
| public synchronized Runnable getClient() { |
| if(clients.isEmpty()) { |
| return null; |
| } |
| return (Runnable) clients.remove(0); |
| } |
| |
| /** |
| * @since 1.4.5 |
| */ |
| public boolean isClientAvailable() { |
| if(clients.isEmpty()) { |
| return false; |
| } else { |
| return true; |
| } |
| } |
| |
| public void close() throws Exception { |
| pool.close(); |
| } |
| |
| public void clear() throws Exception { |
| pool.clear(); |
| } |
| |
| /** |
| * Return the number of instances currently borrowed from my pool. |
| * @since 1.4.1 |
| */ |
| public int getNumActive() { |
| return pool.getNumActive(); |
| } |
| |
| /** |
| * Return the number of instances currently idle in my pool. |
| * @since 1.4.1 |
| */ |
| public int getNumIdle() { |
| return pool.getNumIdle(); |
| } |
| |
| /** |
| * Returns iterator containing all the active |
| * threads i.e ClientHandler handling connected clients. |
| * @since 1.3.1 |
| */ |
| public final Iterator getAllClientThread() { |
| return ((QSObjectPool)pool).getAllActiveObjects(); |
| } |
| |
| public Object getObjectToSynchronize() { |
| return ((QSObjectPool)pool).getObjectToSynchronize(); |
| } |
| |
| /** |
| * Returns PoolConfig object that configured this pool |
| * @since 1.4.5 |
| */ |
| public PoolConfig getPoolConfig() { |
| return poolConfig; |
| } |
| |
| /** |
| * Sets the maximum threads allowed for nio write. If set to 0 or less no limit is |
| * imposed. |
| * @since 1.4.6 |
| */ |
| public void setMaxThreadsForNioWrite(int count) { |
| this.maxThreadsForNioWrite = count; |
| } |
| |
| /** |
| * Returns the maximum threads allowed for nio write |
| * @since 1.4.6 |
| */ |
| public int getMaxThreadsForNioWrite() { |
| return maxThreadsForNioWrite; |
| } |
| |
| /** |
| * Notifies when NIO write is complete. |
| * @since 1.4.6 |
| */ |
| protected void nioWriteEnd() { |
| countNioWriteThreads--; |
| if(countNioWriteThreads<0) { |
| logger.warning("countNioWriteThreads should not go less than 0"); |
| countNioWriteThreads = 0; |
| } |
| } |
| |
| /** |
| * Notifies when NIO write is about to start. |
| * @since 1.4.6 |
| */ |
| protected void nioWriteStart() { |
| countNioWriteThreads++; |
| } |
| |
| /** |
| * Method to suggest if nio write should be sent for processing. |
| * @since 1.4.6 |
| */ |
| public boolean shouldNioWriteHappen() { |
| if(maxThreadsForNioWrite <= 0 || |
| countNioWriteThreads < maxThreadsForNioWrite) { |
| return true; |
| } else { |
| return false; |
| } |
| } |
| } |