001: /*
002: * This file is part of the QuickServer library
003: * Copyright (C) QuickServer.org
004: *
005: * Use, modification, copying and distribution of this software is subject to
006: * the terms and conditions of the GNU Lesser General Public License.
007: * You should have received a copy of the GNU LGP License along with this
008: * library; if not, you can download a copy from <http://www.quickserver.org/>.
009: *
010: * For questions, suggestions, bug-reports, enhancement-requests etc.
011: * visit http://www.quickserver.org
012: *
013: */
014:
015: package org.quickserver.util.pool.thread;
016:
017: import java.util.*;
018: import org.quickserver.util.pool.*;
019: import org.apache.commons.pool.*;
020: import org.apache.commons.pool.impl.*;
021: import org.quickserver.net.server.*;
022: import org.quickserver.util.xmlreader.PoolConfig;
023: import java.util.logging.*;
024:
025: /**
026: * This is a class for managing the pool of threads for
027: * handling clients.
028: * @author Akshathkumar Shetty
029: * @since 1.3
030: */
031: public class ClientPool {
032: private static Logger logger = Logger.getLogger(ClientPool.class
033: .getName());
034:
035: protected List clients = new ArrayList(3);
036: protected ObjectPool pool;
037: protected PoolConfig poolConfig;
038: private int countNioWriteThreads; //v1.4.6
039: private int maxThreadsForNioWrite = 10;
040:
041: public ClientPool(QSObjectPool objectPool, PoolConfig poolConfig) {
042: this .poolConfig = poolConfig;
043: pool = objectPool;
044: }
045:
046: public ObjectPool getObjectPool() {
047: return pool;
048: }
049:
050: public void addClient(Runnable r) throws NoSuchElementException {
051: addClient(r, false);
052: }
053:
054: public synchronized void addClient(Runnable r, boolean keepObjOnFail)
055: throws NoSuchElementException {
056: //logger.finest("Adding Runnable: "+r);
057: clients.add(r);
058: ClientThread ct = null;
059: try {
060: ct = (ClientThread) pool.borrowObject();
061:
062: if (ct.isReady() == false) {
063: //ct.start();
064: wait(500); //timeout was just in case :-)
065: //Thread.yield();
066: } else {
067: synchronized (ct) {
068: ct.notify();
069: }
070: }
071: } catch (NoSuchElementException e) {
072: logger.info("No free threads: " + e);
073: if (keepObjOnFail == false)
074: clients.remove(r);
075: throw e;
076: } catch (Exception e) {
077: logger.warning("Error in addClient: " + e
078: + ", Closing client: " + (ClientHandler) r);
079: try {
080: ((ClientHandler) r).forceClose();
081: } catch (Exception er) {
082: logger.warning("Error closing client: " + er);
083: }
084: try {
085: if (ct != null)
086: pool.returnObject(ct);
087: } catch (Exception er) {
088: logger.warning("Error in returning thread: " + er);
089: }
090: }
091: }
092:
093: public synchronized void returnObject(Object object) {
094: try {
095: pool.returnObject(object);
096: } catch (Exception e) {
097: logger.warning("IGONRED: Error while returning object : "
098: + e);
099: ((Thread) object).interrupt();
100: }
101: }
102:
103: public synchronized Runnable getClient() {
104: if (clients.size() == 0) {
105: return null;
106: }
107: return (Runnable) clients.remove(0);
108: }
109:
110: /**
111: * @since 1.4.5
112: */
113: public boolean isClientAvailable() {
114: if (clients.size() == 0) {
115: return false;
116: } else {
117: return true;
118: }
119: }
120:
121: protected void finalize() throws Throwable {
122: try {
123: close();
124: } catch (Exception e) {
125: logger.warning("IGONRED:finalize in pool close : " + e);
126: }
127: super .finalize();
128: }
129:
130: public void close() throws Exception {
131: pool.close();
132: }
133:
134: public void clear() throws Exception {
135: pool.clear();
136: }
137:
138: /**
139: * Return the number of instances currently borrowed from my pool.
140: * @since 1.4.1
141: */
142: public int getNumActive() {
143: return pool.getNumActive();
144: }
145:
146: /**
147: * Return the number of instances currently idle in my pool.
148: * @since 1.4.1
149: */
150: public int getNumIdle() {
151: return pool.getNumIdle();
152: }
153:
154: /**
155: * Returns iterator containing all the active
156: * threads i.e ClientHandler handling connected clients.
157: * @since 1.3.1
158: */
159: public final Iterator getAllClientThread() {
160: return ((QSObjectPool) pool).getAllActiveObjects();
161: }
162:
163: public Object getObjectToSynchronize() {
164: return ((QSObjectPool) pool).getObjectToSynchronize();
165: }
166:
167: /**
168: * Returns PoolConfig object that configured this pool
169: * @since 1.4.5
170: */
171: public PoolConfig getPoolConfig() {
172: return poolConfig;
173: }
174:
175: /**
176: * Sets the maximum threads allowed for nio write. If set to 0 or less no limit is
177: * imposed.
178: * @since 1.4.6
179: */
180: public void setMaxThreadsForNioWrite(int count) {
181: this .maxThreadsForNioWrite = count;
182: }
183:
184: /**
185: * Returns the maximum threads allowed for nio write
186: * @since 1.4.6
187: */
188: public int getMaxThreadsForNioWrite() {
189: return maxThreadsForNioWrite;
190: }
191:
192: /**
193: * Notifies when NIO write is complete.
194: * @since 1.4.6
195: */
196: protected void nioWriteEnd() {
197: countNioWriteThreads--;
198: if (countNioWriteThreads < 0) {
199: logger
200: .warning("countNioWriteThreads should not go less than 0");
201: countNioWriteThreads = 0;
202: }
203: }
204:
205: /**
206: * Notifies when NIO write is about to start.
207: * @since 1.4.6
208: */
209: protected void nioWriteStart() {
210: countNioWriteThreads++;
211: }
212:
213: /**
214: * Method to suggest if nio write should be sent for processing.
215: * @since 1.4.6
216: */
217: public boolean shouldNioWriteHappen() {
218: if (maxThreadsForNioWrite <= 0
219: || countNioWriteThreads < maxThreadsForNioWrite) {
220: return true;
221: } else {
222: return false;
223: }
224: }
225: }
|