00001
package com.quadcap.net.server;
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
import java.io.IOException;
00042
00043
import java.util.Hashtable;
00044
import java.util.Iterator;
00045
import java.util.Properties;
00046
00047
import java.net.ServerSocket;
00048
00049
import com.quadcap.util.collections.ArrayQueue;
00050
import com.quadcap.util.collections.IntMap;
00051
00052
00053
00054
00055
00056
00057
00058 public class Server {
00059 Class
workerClass;
00060 Object
workerLock =
new Object();
00061 Object
context;
00062 ThreadGroup
threads;
00063 IntMap
allWorkers;
00064 ArrayQueue
workers;
00065 int numWorkers = 0;
00066 int maxWorkers = 128;
00067 long shutdownInterval = 2000L;
00068 String
name;
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109 public Server(Properties props, Object context)
00110
throws ClassNotFoundException
00111 {
00112
this.context =
context;
00113
this.workerClass = Class.forName(props.getProperty(
"workerClass"));
00114
00115
int max = Integer.parseInt(props.getProperty(
"maxWorkers",
"64"));
00116
this.workers =
new ArrayQueue(max);
00117
this.allWorkers =
new IntMap(max / 3);
00118
this.name = props.getProperty(
"name",
"server");
00119
this.threads =
new ThreadGroup(
name);
00120
this.shutdownInterval =
00121 Long.parseLong(props.getProperty(
"shutdownInterval",
"2000"));
00122
00123 }
00124
00125 public ThreadGroup
getThreadGroup() {
00126
return threads;
00127 }
00128
00129 public void startAcceptor(Properties props)
throws IOException {
00130
int port = Integer.parseInt(props.getProperty(
"port"));
00131
int queueDepth =
00132 Integer.parseInt(props.getProperty(
"queueDepth",
"16"));
00133
Acceptor acceptor =
new Acceptor(
this, port, queueDepth);
00134 Thread t =
new Thread(
threads, acceptor);
00135 t.start();
00136 }
00137
00138
00139 public Worker getIdleWorker() throws Exception {
00140
synchronized (
workerLock) {
00141
while (
true) {
00142
Worker w = (
Worker)
workers.popFront();
00143
if (w != null)
return w;
00144
00145
if (
numWorkers <
maxWorkers) {
00146
return newWorker();
00147 }
else {
00148
try {
00149
workerLock.wait();
00150 }
catch (InterruptedException ee) {
00151 }
00152 }
00153 }
00154 }
00155 }
00156
00157 public int getIdleWorkers(
Worker[] workerv)
throws Exception {
00158
int cnt = 0;
00159
synchronized (
workerLock) {
00160
for (; cnt < workerv.length; cnt++) {
00161
Worker w = (
Worker)
workers.popFront();
00162
if (w != null) {
00163 workerv[cnt] = w;
00164 }
else {
00165
if (
numWorkers <
maxWorkers) {
00166 workerv[cnt] =
newWorker();
00167 }
else if (cnt > 0) {
00168
break;
00169 }
else {
00170
try {
00171
workerLock.wait();
00172 }
catch (InterruptedException ee) {
00173 }
00174 }
00175 }
00176 }
00177 }
00178
return cnt;
00179 }
00180
00181 public void returnIdleWorker(
Worker w) {
00182
synchronized (
workerLock) {
00183
workers.pushFront(w);
00184
workerLock.notifyAll();
00185 }
00186 }
00187
00188 public void workerDone(
Worker w) {
00189
allWorkers.remove(w.
getId());
00190
workerLock.notifyAll();
00191 }
00192
00193 public Worker newWorker() throws Exception {
00194
Worker w = (
Worker)
workerClass.newInstance();
00195 w.
init(
this,
context,
name);
00196
allWorkers.put(w.
getId(), w);
00197
new Thread(
threads, w).start();
00198
return w;
00199 }
00200
00201 public void stop() {
00202 Iterator iter =
allWorkers.keys();
00203
while (iter.hasNext()) {
00204
int id = ((Integer)iter.next()).intValue();
00205
Worker w = (
Worker)
allWorkers.get(
id);
00206 w.
stop();
00207 }
00208
try { Thread.sleep(
shutdownInterval); }
catch (Throwable t) {}
00209
00210
if (
threads.activeCount() > 0) {
00211 Thread[] ts =
new Thread[
threads.activeCount()];
00212
int cnt =
threads.enumerate(ts);
00213
for (
int i = 0; i < cnt; i++) {
00214 Thread t = ts[i];
00215
if (!t.isInterrupted()) {
00216 t.interrupt();
00217 }
00218 }
00219
try { Thread.sleep(
shutdownInterval); }
catch (Throwable t) {}
00220 cnt =
threads.enumerate(ts);
00221
for (
int i = 0; i < cnt; i++) {
00222 Thread t = ts[i];
00223
try {
00224 t.join(
shutdownInterval/10);
00225 }
catch (Throwable th) {
00226 } finally {
00227
try {
00228 t.stop();
00229 }
catch (Throwable th2) {
00230 }
00231 }
00232 }
00233 }
00234 }
00235 }