Source Code Cross Referenced for SocketClientFactory.java in  » Web-Server » Jigsaw » org » w3c » jigsaw » http » socket » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Web Server » Jigsaw » org.w3c.jigsaw.http.socket 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        // SocketClientFactory.java
0002:        // $Id: SocketClientFactory.java,v 1.48 2004/08/30 16:04:44 ylafon Exp $
0003:        // (c) COPYRIGHT MIT and INRIA, 1996.
0004:        // Please first read the full copyright statement in file COPYRIGHT.html
0005:
0006:        package org.w3c.jigsaw.http.socket;
0007:
0008:        import java.io.IOException;
0009:        import java.io.PrintStream;
0010:
0011:        import java.net.InetAddress;
0012:        import java.net.ServerSocket;
0013:        import java.net.Socket;
0014:        import java.net.URL;
0015:
0016:        import org.w3c.jigsaw.http.Client;
0017:        import org.w3c.jigsaw.http.ClientFactory;
0018:        import org.w3c.jigsaw.http.httpd;
0019:
0020:        import org.w3c.jigsaw.config.PropertySet;
0021:
0022:        import org.w3c.util.LRUAble;
0023:        import org.w3c.util.LRUList;
0024:        import org.w3c.util.ObservableProperties;
0025:        import org.w3c.util.PropertyMonitoring;
0026:        import org.w3c.util.Status;
0027:        import org.w3c.util.SyncLRUList;
0028:        import org.w3c.util.ThreadCache;
0029:
0030:        class DebugThread extends Thread {
0031:            SocketClientFactory pool = null;
0032:
0033:            public void run() {
0034:                while (true) {
0035:                    try {
0036:                        sleep(1000 * 10);
0037:                        // Display some client statistics:
0038:                        SocketClientState cs = null;
0039:                        cs = (SocketClientState) pool.freeList.getHead();
0040:                        while (cs != null) {
0041:                            System.out
0042:                                    .println(cs.client + " reqcount="
0043:                                            + cs.client.getRequestCount()
0044:                                            + ", bindcount="
0045:                                            + cs.client.getBindCount());
0046:                            cs = (SocketClientState) pool.freeList
0047:                                    .getNext((LRUAble) cs);
0048:                        }
0049:                        System.out.println("freeCount =" + pool.freeCount);
0050:                        System.out.println("idleCount =" + pool.idleCount);
0051:                        System.out.println("totalCount=" + pool.clientCount);
0052:                        System.out.println("estimCount=" + pool.clientEstim);
0053:                        System.out.println("Average: " + pool.loadavg);
0054:                    } catch (Exception ex) {
0055:                        ex.printStackTrace();
0056:                    }
0057:                }
0058:            }
0059:
0060:            DebugThread(SocketClientFactory pool) {
0061:                this .pool = pool;
0062:                setPriority(Thread.MAX_PRIORITY);
0063:            }
0064:        }
0065:
0066:        /**
0067:         * The client pool is a kind of client factory.
0068:         * Each time the server gets a new connection, it calls the client pool
0069:         * to bound a client object (newly created or spared) to handle it.
0070:         */
0071:
0072:        public class SocketClientFactory implements  ClientFactory,
0073:                PropertyMonitoring, Status {
0074:
0075:            private static final boolean debug = false;
0076:            private static final boolean debugstats = false;
0077:            private static final boolean debugthread = false;
0078:
0079:            public static final int MINSPARE_FREE = 5;
0080:            public static final int MAXSPARE_FREE = 10;
0081:            public static final int MAXSPARE_IDLE = 20;
0082:            public static final int MAXTHREADS = 40;
0083:            public static final int MAXCLIENTS = 32;
0084:            public static final int IDLETO = 10000;
0085:
0086:            public static final int AVG_LIGHT = 1;
0087:            public static final int AVG_NORMAL = 2;
0088:            public static final int AVG_HIGH = 3;
0089:            public static final int AVG_DEAD = 4;
0090:
0091:            // FIXME doc
0092:            public final static String MINSPARE_FREE_P = "org.w3c.jigsaw.http.socket.SocketClientFactory.minFree";
0093:            // FIXME doc
0094:            public final static String MAXSPARE_FREE_P = "org.w3c.jigsaw.http.socket.SocketClientFactory.maxFree";
0095:            // FIXME doc
0096:            public final static String MAXSPARE_IDLE_P = "org.w3c.jigsaw.http.socket.SocketClientFactory.maxIdle";
0097:            // FIXME doc
0098:            public final static String MAXTHREADS_P = "org.w3c.jigsaw.http.socket.SocketClientFactory.maxThreads";
0099:            // FIXME doc
0100:            public final static String MAXCLIENTS_P = "org.w3c.jigsaw.http.socket.SocketClientFactory.maxClients";
0101:            // FIXME doc
0102:            public final static String IDLETO_P = "org.w3c.jigsaw.http.socket.SocketClientFactory.idleTimeout";
0103:            // FIXME doc
0104:            public final static String BINDADDR_P = "org.w3c.jigsaw.http.socket.SocketClientFactory.bindAddress";
0105:            // FIXME doc
0106:            public final static String TIMEOUT_P = "org.w3c.jigsaw.http.socket.SocketClientFactory.timeout";
0107:
0108:            int minFree = 0;
0109:            int maxFree = 0;
0110:            int maxIdle = 0;
0111:            int maxClients = 0;
0112:            InetAddress bindAddr = null;
0113:            int timeout = 0;
0114:
0115:            int count = 0; // number of created clients.
0116:            httpd server = null;
0117:            ObservableProperties props = null;
0118:            int busyCount = 0; // number of busy clients.
0119:
0120:            LRUList idleList = null;
0121:            LRUList freeList = null;
0122:
0123:            SocketClientState csList = null;
0124:
0125:            int idleCount = 0;
0126:            int freeCount = 0;
0127:            int clientCount = 0;
0128:            int clientEstim = 0;
0129:
0130:            ThreadCache threadcache = null;
0131:
0132:            int loadavg = AVG_LIGHT;
0133:
0134:            boolean alive = true;
0135:
0136:            /**
0137:             * Give the status of this class as a partial HTML text which will be added
0138:             * into a block level element
0139:             * @return a String, the generated HTML
0140:             */
0141:            public String getHTMLStatus() {
0142:                int idle = 0;
0143:                int free = 0;
0144:                int used = 0;
0145:                int bndc = 0;
0146:                int reqc = 0;
0147:                int bnd, req;
0148:                StringBuffer sb = new StringBuffer();
0149:                SocketClientState cs = null;
0150:                StringBuffer sb1 = null;
0151:                if (debugstats) {
0152:                    sb1 = new StringBuffer();
0153:                }
0154:                // used clients
0155:                cs = csList;
0156:                if (debugstats) {
0157:                    sb1.append("<table border=\"1\" class=\"idle\">\n"
0158:                            + "<caption>Used Clients"
0159:                            + "</caption><tr><th>Id</th><th>BindCount</th>"
0160:                            + "<th>ReqCount</th><th>Diff</th>"
0161:                            + "<th>BoundTo</th><th>URI</th></tr>\n");
0162:                }
0163:                while (cs != null) {
0164:                    if (cs.status == SocketClientState.C_BUSY) {
0165:                        InetAddress ia = cs.client.getInetAddress();
0166:                        bnd = cs.client.getBindCount();
0167:                        req = cs.client.getRequestCount();
0168:                        if (debugstats) {
0169:                            sb1.append("<tr><td>");
0170:                            sb1.append(cs.id);
0171:                            sb1.append("</td><td>");
0172:                            sb1.append(bnd);
0173:                            sb1.append("</td><td>");
0174:                            sb1.append(req);
0175:                            sb1.append("</td><td>");
0176:                            sb1.append(req - bnd);
0177:                            sb1.append("</td><td>");
0178:                            if (ia == null) {
0179:                                sb1.append("Unbound");
0180:                            } else {
0181:                                sb1.append(cs.client.getInetAddress()
0182:                                        .getHostAddress());
0183:                            }
0184:                            sb1.append("</td><td>");
0185:                            if (cs.client.currentURI == null) {
0186:                                sb1.append('-');
0187:                            } else {
0188:                                String u = cs.client.currentURI.toString();
0189:                                for (int i = 0; i < u.length(); i++) {
0190:                                    char ch = u.charAt(i);
0191:                                    switch (ch) {
0192:                                    case '<':
0193:                                        sb1.append("&lt;");
0194:                                        break;
0195:                                    case '>':
0196:                                        sb1.append("&gt;");
0197:                                        break;
0198:                                    case '&':
0199:                                        sb1.append("&amp;");
0200:                                        break;
0201:                                    default:
0202:                                        sb1.append(ch);
0203:                                        break;
0204:                                    }
0205:                                }
0206:                            }
0207:                            sb1.append("</td></tr>\n");
0208:                        }
0209:                        used++;
0210:                        bndc += bnd;
0211:                        reqc += req;
0212:                    }
0213:                    cs = cs.csnext;
0214:                }
0215:                if (debugstats) {
0216:                    sb1.append("</table>\n");
0217:                }
0218:                // idle clients
0219:                cs = (SocketClientState) idleList.getHead();
0220:                if (debugstats) {
0221:                    sb1
0222:                            .append("<table border=\"1\" class=\"idle\">\n<caption>Idle "
0223:                                    + "Clients</caption><tr><th>Id<th>BindCount<th>ReqCount"
0224:                                    + "<th>Diff<th>BoundTo</tr>\n");
0225:                }
0226:                while (cs != null) {
0227:                    InetAddress ia = cs.client.getInetAddress();
0228:                    idle++;
0229:                    bnd = cs.client.getBindCount();
0230:                    req = cs.client.getRequestCount();
0231:                    if (debugstats) {
0232:                        sb1.append("<tr><td>"
0233:                                + cs.id
0234:                                + "<td>"
0235:                                + bnd
0236:                                + "<td>"
0237:                                + req
0238:                                + "<td>"
0239:                                + (req - bnd)
0240:                                + "<td>"
0241:                                + ((ia == null) ? "Unbound" : cs.client
0242:                                        .getInetAddress().getHostAddress())
0243:                                + "</tr>\n");
0244:                    }
0245:                    bndc += bnd;
0246:                    reqc += req;
0247:                    cs = (SocketClientState) idleList.getNext(cs);
0248:                }
0249:                if (debugstats) {
0250:                    sb1.append("</table>\n");
0251:                }
0252:                // free clients
0253:                cs = (SocketClientState) freeList.getHead();
0254:                if (debugstats) {
0255:                    sb1
0256:                            .append("<table border=\"1\" class=\"idle\">\n"
0257:                                    + "<caption>Free Clients"
0258:                                    + "</caption><tr><th>Id<th>BindCount<th>ReqCount<th>"
0259:                                    + "Diff</tr>\n");
0260:                }
0261:                while (cs != null) {
0262:                    free++;
0263:                    bnd = cs.client.getBindCount();
0264:                    req = cs.client.getRequestCount();
0265:                    if (debugstats) {
0266:                        sb1.append("<tr><td>" + cs.id + "<td>" + bnd + "<td>"
0267:                                + req + "<td>" + (req - bnd) + "\n");
0268:                    }
0269:                    bndc += bnd;
0270:                    reqc += req;
0271:                    cs = (SocketClientState) freeList.getNext(cs);
0272:                }
0273:                if (debugstats) {
0274:                    sb1.append("</table>\n");
0275:                }
0276:
0277:                // stats
0278:                sb
0279:                        .append("<table border class=\"thread\">\n<caption>Thread counts"
0280:                                + "</caption><tr><th>free<th>idle<th>used"
0281:                                + "<th>estim<th>total<th>Load</tr>");
0282:                sb.append("<tr><td>");
0283:                sb.append(freeCount);
0284:                sb.append('(');
0285:                sb.append(free);
0286:                sb.append(")</td><td>");
0287:                sb.append(idleCount);
0288:                sb.append('(');
0289:                sb.append(idle);
0290:                sb.append(")</td><td>");
0291:                sb.append(clientCount - freeCount - idleCount);
0292:                sb.append('(');
0293:                sb.append(used);
0294:                sb.append(")</td><td>");
0295:                sb.append(clientEstim);
0296:                sb.append("</td><td>");
0297:                sb.append(clientCount);
0298:                sb.append("</td><td>");
0299:                sb.append(loadavg);
0300:                sb.append("</td></tr></table>\n");
0301:                // usage stats
0302:                sb
0303:                        .append("<table border class=\"usage\">\n<caption>Usage</caption>"
0304:                                + "<tr><th>ReqCount<th>BindCount<th>Diff</tr>\n<tr><td>");
0305:                sb.append(reqc);
0306:                sb.append("</td><td>");
0307:                sb.append(bndc);
0308:                sb.append("</td><td>");
0309:                sb.append(reqc - bndc);
0310:                sb.append("</td></tr></table>\n");
0311:                if (debugstats) {
0312:                    sb.append(sb1);
0313:                }
0314:
0315:                if (debugstats) {
0316:                    cs = csList;
0317:                    sb
0318:                            .append("<table border=\"1\" class=\"idle\">\n<caption>General"
0319:                                    + " Status</caption><tr><th>Id<th>Client<th>"
0320:                                    + "Status<th>marked<th>Thread</tr>\n");
0321:                    while (cs != null) {
0322:                        sb.append("<tr><td>" + cs.id + "<td>"
0323:                                + ((cs.client == null) ? "None" : "bound")
0324:                                + "<td>");
0325:                        switch (cs.status) {
0326:                        case SocketClientState.C_IDLE:
0327:                            sb.append("Idle");
0328:                            break;
0329:                        case SocketClientState.C_BUSY:
0330:                            sb.append("Busy");
0331:                            break;
0332:                        case SocketClientState.C_FREE:
0333:                            sb.append("Free");
0334:                            break;
0335:                        case SocketClientState.C_KILL:
0336:                            sb.append("Kill");
0337:                            break;
0338:                        case SocketClientState.C_FIN:
0339:                            sb.append("Fin");
0340:                            break;
0341:                        }
0342:                        sb.append("<td>" + cs.marked);
0343:                        if (cs.client != null) {
0344:                            sb.append("<td>" + cs.client.thread + "</tr>\n");
0345:                        } else {
0346:                            sb.append("<td>No CLient</tr>\n");
0347:                        }
0348:                        cs = cs.csnext;
0349:                    }
0350:                    sb.append("</table>\n");
0351:                }
0352:                return sb.toString();
0353:            }
0354:
0355:            /**
0356:             * Some property have changed, update our setting.
0357:             * @param name The name of the property that has changed.
0358:             * @return A boolean, <strong>true</strong> if we updated ourself 
0359:             *    successfully.
0360:             */
0361:            public boolean propertyChanged(String name) {
0362:                httpd s = server;
0363:                if (name.equals(MINSPARE_FREE_P)) {
0364:                    minFree = props.getInteger(MINSPARE_FREE_P, minFree);
0365:                } else if (name.equals(MAXSPARE_FREE_P)) {
0366:                    maxFree = props.getInteger(MAXSPARE_FREE_P, maxFree);
0367:                } else if (name.equals(MAXSPARE_IDLE_P)) {
0368:                    maxIdle = props.getInteger(MAXSPARE_IDLE_P, maxIdle);
0369:                } else if (name.equals(MAXTHREADS_P)) {
0370:                    int maxThreads = props.getInteger(MAXTHREADS_P, -1);
0371:                    if (maxThreads > 0)
0372:                        threadcache.setCachesize(maxThreads);
0373:                } else if (name.equals(IDLETO_P)) {
0374:                    int idleto = props.getInteger(IDLETO_P, -1);
0375:                    if (idleto > 0) {
0376:                        threadcache.setIdleTimeout(idleto);
0377:                    }
0378:                } else if (name.equals(MAXCLIENTS_P)) {
0379:                    int newmax = props.getInteger(MAXCLIENTS_P, -1);
0380:                    if (newmax > maxClients) {
0381:                        for (int i = maxClients - newmax; --i >= 0;)
0382:                            addClient(true);
0383:                    } else if (newmax > 0) {
0384:                        maxClients = newmax;
0385:                    }
0386:                } else if (name.equals(BINDADDR_P)) {
0387:                    try {
0388:                        bindAddr = InetAddress.getByName(props.getString(
0389:                                BINDADDR_P, null));
0390:                    } catch (Exception ex) {
0391:                        // nothing
0392:                    }
0393:                } else if (name.equals(TIMEOUT_P)) {
0394:                    timeout = props.getInteger(IDLETO_P, timeout);
0395:                }
0396:                return true;
0397:            }
0398:
0399:            /**
0400:             * Remove this client state from the glohbal client list.
0401:             * @param cs The client state to remove from the list.
0402:             */
0403:
0404:            protected synchronized void deleteClient(SocketClientState cs) {
0405:                synchronized (csList) {
0406:                    if (cs.csprev == null) {
0407:                        csList = cs.csnext;
0408:                    } else if (cs.csnext == null) {
0409:                        cs.csprev.csnext = null;
0410:                    } else {
0411:                        cs.csprev.csnext = cs.csnext;
0412:                        cs.csnext.csprev = cs.csprev;
0413:                    }
0414:                }
0415:            }
0416:
0417:            /**
0418:             * Factory for creating a new client for this pool.
0419:             * @param server  the target http daemon 
0420:             * @param state  the client state holder
0421:             * @return a new socket client
0422:             */
0423:            protected SocketClient createClient(httpd server,
0424:                    SocketClientState state) {
0425:                return new SocketClient(server, this , state);
0426:            }
0427:
0428:            /**
0429:             * Create a new client for this pool.
0430:             * @param free A boolean, if <strong>true</strong> the client is inserted
0431:             * straight into the free list, otherwise, it is not plugged into any
0432:             * list.
0433:             * @return A SocketClientState instance, if creation of a new client was
0434:             * allowed, <strong>null</strong> if no more clients could be created.
0435:             */
0436:
0437:            protected synchronized SocketClientState addClient(boolean free) {
0438:                // Create a new client. 
0439:                csList = new SocketClientState(csList);
0440:                SocketClientState cs = csList;
0441:                SocketClient client = createClient(server, cs);
0442:                cs.client = client;
0443:                clientCount++;
0444:                clientEstim++;
0445:                // Plug into free LRU if required:
0446:                if (free) {
0447:                    cs.status = SocketClientState.C_FREE;
0448:                    freeList.toHead(cs);
0449:                    freeCount++;
0450:                }
0451:                return cs;
0452:            }
0453:
0454:            /**
0455:             * We are not using synchronized functions to speed up things, 
0456:             * but it is sometime useful to check that clients are not in a bad
0457:             * shape
0458:             */
0459:            private final void checkDeadClients() {
0460:                SocketClientState cs = null;
0461:                cs = csList;
0462:                boolean check = true;
0463:                int idlecount = 0;
0464:                int freecount = 0;
0465:                int clientcount = 0;
0466:
0467:                while (cs != null) {
0468:                    if (cs.client != null) {
0469:                        clientcount++;
0470:                        switch (cs.status) {
0471:                        case SocketClientState.C_BUSY:
0472:                            if (cs.client.thread == null) {
0473:                                if (cs.marked) {
0474:                                    if (clientEstim <= maxClients) {
0475:                                        cs.marked = false;
0476:                                        ++freeCount;
0477:                                        updateLoadAverage();
0478:                                        freeList.toHead(cs);
0479:                                        cs.status = SocketClientState.C_FREE;
0480:                                        cs.client.done = true;
0481:                                    }
0482:                                    check = false;
0483:                                } else {
0484:                                    cs.marked = true;
0485:                                }
0486:                            }
0487:                            break;
0488:                        case SocketClientState.C_FREE:
0489:                            freecount++;
0490:                            cs.marked = false;
0491:                            break;
0492:                        default:
0493:                            cs.marked = false;
0494:                            break;
0495:                        }
0496:                    }
0497:                    cs = cs.csnext;
0498:                }
0499:                // sanity check
0500:                if (freecount != freeCount) {
0501:                    cs = (SocketClientState) idleList.getHead();
0502:                    while (cs != null) {
0503:                        idlecount++;
0504:                        cs = (SocketClientState) idleList.getNext(cs);
0505:                    }
0506:                    cs = (SocketClientState) freeList.getHead();
0507:                    freecount = 0;
0508:                    while (cs != null) {
0509:                        freecount++;
0510:                        cs = (SocketClientState) freeList.getNext(cs);
0511:                    }
0512:                    freeCount = freecount;
0513:                    idleCount = idlecount;
0514:                }
0515:            }
0516:
0517:            /**
0518:             * Update our idea of the current load.
0519:             * The one important invariant here, is that whenever the free list
0520:             * becomes empty, then the load average should be equals to
0521:             * <strong>AVG_DEAD</strong>. This ensures that the server will start 
0522:             * dropping connections.
0523:             *
0524:             */
0525:            private final void updateLoadAverage() {
0526:                int oldavg = loadavg;
0527:                if (freeCount >= maxFree) {
0528:                    loadavg = AVG_LIGHT;
0529:                } else if ((freeCount >= minFree) || (idleCount >= maxIdle)) {
0530:                    if ((loadavg = AVG_NORMAL) < oldavg) {
0531:                        server.thread.setPriority(Thread.MAX_PRIORITY);
0532:                    }
0533:                } else if (freeCount > 0) {
0534:                    /* idleCount < MINSPARE_IDLE */
0535:                    if ((loadavg = AVG_HIGH) > oldavg) {
0536:                        // first ensure the state is sane
0537:                        //		checkDeadClients();
0538:                        server.thread.setPriority(server
0539:                                .getClientThreadPriority() - 2);
0540:                    }
0541:                } else {
0542:                    loadavg = AVG_DEAD;
0543:                }
0544:            }
0545:
0546:            private final synchronized void incrClientCount() {
0547:                ++clientCount;
0548:                ++clientEstim;
0549:                updateLoadAverage();
0550:            }
0551:
0552:            private final synchronized void decrClientCount() {
0553:                --clientCount;
0554:                updateLoadAverage();
0555:            }
0556:
0557:            private final synchronized boolean incrFreeCount() {
0558:                if (clientEstim > maxClients) {
0559:                    clientEstim--;
0560:                    return false;
0561:                }
0562:                ++freeCount;
0563:                updateLoadAverage();
0564:                return true;
0565:            }
0566:
0567:            private final synchronized boolean decrFreeCount() {
0568:                if (freeCount > 0) {
0569:                    --freeCount;
0570:                    updateLoadAverage();
0571:                    return true;
0572:                } else {
0573:                    return false;
0574:                }
0575:            }
0576:
0577:            private final synchronized boolean incrIdleCount() {
0578:                if ((loadavg > AVG_HIGH) || (idleCount + 1 >= maxIdle))
0579:                    return false;
0580:                ++idleCount;
0581:                updateLoadAverage();
0582:                return true;
0583:            }
0584:
0585:            private final synchronized boolean decrIdleCount() {
0586:                if (idleCount > 0) {
0587:                    --idleCount;
0588:                    updateLoadAverage();
0589:                    return true;
0590:                } else {
0591:                    return false;
0592:                }
0593:            }
0594:
0595:            /**
0596:             * Removes an idle client from the list, updates only the idle list
0597:             * as the free count has already be accessed
0598:             * @param the socket client to remove from the idle list
0599:             */
0600:            protected boolean idleClientRemove(SocketClient client) {
0601:                // If the client pool has shut down, exit straight:
0602:                if (!alive)
0603:                    return false;
0604:                SocketClientState cs = client.state;
0605:                synchronized (csList) {
0606:                    switch (cs.status) {
0607:                    case SocketClientState.C_IDLE:
0608:                        decrIdleCount();
0609:                        idleList.remove(cs);
0610:                        cs.status = SocketClientState.C_FREE;
0611:                        break;
0612:                    case SocketClientState.C_KILL:
0613:                    case SocketClientState.C_BUSY:
0614:                    default:
0615:                        break;
0616:                    }
0617:                }
0618:                return true;
0619:            }
0620:
0621:            /**
0622:             * Notify that this client has finished with its connection.
0623:             * If the pool wants the client to be freed (because it has too many of 
0624:             * them), it makes the client kill itself (which will trigger a call to
0625:             * the clientFinished method, were enventual cleanup is performed).
0626:             * @param client The client that is done with its connection.
0627:             */
0628:
0629:            protected boolean clientConnectionFinished(SocketClient client) {
0630:                // If the client pool has shut down, exit straight:
0631:                if (!alive)
0632:                    return false;
0633:                SocketClientState cs = client.state;
0634:                synchronized (csList) {
0635:                    switch (cs.status) {
0636:                    case SocketClientState.C_IDLE:
0637:                        decrIdleCount();
0638:                        idleList.remove(cs);
0639:                        break;
0640:                    case SocketClientState.C_BUSY:
0641:                    case SocketClientState.C_KILL:
0642:                        break;
0643:                    case SocketClientState.C_FREE:
0644:                        // already freeed?
0645:                        if (client.done) {
0646:                            client.done = false;
0647:                            return true;
0648:                        }
0649:                    default:
0650:                        break;
0651:                    }
0652:                    if (incrFreeCount()) {
0653:                        if (debug)
0654:                            System.out.println(client + ": now free.");
0655:                        cs.status = SocketClientState.C_FREE;
0656:                        freeList.toHead(cs);
0657:                        return true;
0658:                    } else {
0659:                        if (debug)
0660:                            System.out.println(client + ": terminate.");
0661:                        return false;
0662:                    }
0663:                }
0664:            }
0665:
0666:            /**
0667:             * Notify that this client has been killed.
0668:             * @param client The client that has terminate.
0669:             */
0670:
0671:            protected void clientFinished(SocketClient client) {
0672:                // If we're not alive any more, skip:
0673:                if (!alive)
0674:                    return;
0675:                SocketClientState cs = client.state;
0676:                synchronized (csList) {
0677:                    if (debug)
0678:                        System.out.println(client + ": finished " + cs.status);
0679:                    // Otherwise, perform the job:
0680:                    switch (cs.status) {
0681:                    case SocketClientState.C_IDLE:
0682:                        break;
0683:                    case SocketClientState.C_FREE:
0684:                        decrFreeCount();
0685:                        freeList.remove(cs);
0686:                        break;
0687:                    case SocketClientState.C_BUSY:
0688:                    default:
0689:                        String msg = (client
0690:                                + ": finished with unknown status " + cs.status);
0691:                        server.errlog(msg);
0692:                        break;
0693:                    }
0694:                    cs.status = SocketClientState.C_FIN;
0695:                    decrClientCount();
0696:                    deleteClient(cs);
0697:                }
0698:            }
0699:
0700:            /**
0701:             * The client notifies the pool that is has been activated.
0702:             * The client state object is updated to unmark the client as idle.
0703:             * <p>This method needs not be synchronized, as it affect only the client
0704:             * state, <em>not</em> the client list.
0705:             * @param client The activated client.
0706:             */
0707:
0708:            protected void notifyUse(SocketClient client) {
0709:                if (debug)
0710:                    System.out.println(client + ": used.");
0711:                SocketClientState cs = client.state;
0712:                synchronized (csList) {
0713:                    if (cs.status == SocketClientState.C_IDLE) {
0714:                        decrIdleCount();
0715:                        idleList.remove(cs);
0716:                    }
0717:                    cs.status = SocketClientState.C_BUSY;
0718:                }
0719:            }
0720:
0721:            /**
0722:             * The client notifies the pool that it enters idle state.
0723:             * <p>This method needs not be synchronized, as it affect only the client
0724:             * state, <em>not</em> the client list.
0725:             * @param client The client that is going to be idle.
0726:             */
0727:
0728:            protected boolean notifyIdle(SocketClient client) {
0729:                SocketClientState cs = client.state;
0730:                if (alive) {
0731:                    synchronized (csList) {
0732:                        if (incrIdleCount()) {
0733:                            if (debug)
0734:                                System.out.println(client
0735:                                        + ": idle, keep-alive.");
0736:                            cs.status = SocketClientState.C_IDLE;
0737:                            idleList.toHead(cs);
0738:                            return true;
0739:                        } else {
0740:                            if (debug)
0741:                                System.out.println(client + ": idle, closed.");
0742:                            // Kill some old idle connections, give a chance for next:
0743:                            int killsome = Math.max((maxFree - freeCount),
0744:                                    (maxIdle - idleCount));
0745:                            killSomeClients((killsome > 0) ? killsome : 1);
0746:                            // And give it a change if the load is not too high
0747:                            if (incrIdleCount()) {
0748:                                if (debug)
0749:                                    System.out.println(client
0750:                                            + ": idle, keep-alive.");
0751:                                cs.status = SocketClientState.C_IDLE;
0752:                                idleList.toHead(cs);
0753:                                return true;
0754:                            }
0755:                            return false;
0756:                        }
0757:                    }
0758:                } else {
0759:                    if (debug)
0760:                        System.out.println(client + ": idle (dead), closed.");
0761:                    // Kill some old idle connections, give a chance for next:
0762:                    int killsome = Math.max((maxFree - freeCount),
0763:                            (maxIdle - idleCount));
0764:                    killSomeClients((killsome > 0) ? killsome : 1);
0765:                    return false;
0766:                }
0767:            }
0768:
0769:            protected void killSomeClients(int howmany) {
0770:                int count = (howmany > 0) ? howmany : Math.max(
0771:                        (maxFree - freeCount), (maxIdle - idleCount));
0772:                if (debug) {
0773:                    System.out.println("Killing :" + howmany);
0774:                }
0775:                while (--count >= 0) {
0776:                    SocketClientState cs = (SocketClientState) idleList
0777:                            .removeTail();
0778:                    if (cs != null) {
0779:                        synchronized (csList) {
0780:                            if (cs.status == SocketClientState.C_IDLE) {
0781:                                if (debug)
0782:                                    System.out.println(cs.client
0783:                                            + ": kill (some-client).");
0784:                                decrIdleCount();
0785:                                cs.status = SocketClientState.C_KILL;
0786:                                cs.client.unbind();
0787:                            }
0788:                        }
0789:                    } else {
0790:                        break;
0791:                    }
0792:                    // if the load falls back to normal operation, we are all set
0793:                    if ((freeCount > minFree) && (idleCount < maxIdle)) {
0794:                        break;
0795:                    }
0796:                }
0797:            }
0798:
0799:            final protected void killSomeClients() {
0800:                killSomeClients(-1);
0801:            }
0802:
0803:            protected void run(SocketClient client) {
0804:                if (debug)
0805:                    System.out.println(client + ": warming up...");
0806:                boolean threaded = threadcache.getThread(client, true);
0807:                if (debug)
0808:                    System.out.println(client + ": threaded=" + threaded);
0809:            }
0810:
0811:            /**
0812:             * Handle the given connection.
0813:             * Find a free client, bind it to the given socket, and run it. If we
0814:             * have reached our maximum allowed number of clients, kill some
0815:             * connections.
0816:             * <p>A client enters the LRU list (and become a candidate for kill) only
0817:             * after it has handle one request (or if some timeout expires). This is
0818:             * performed by the first call to <code>notifyUse</code> which will
0819:             * silently insert the client into the LRU if it was not there already.
0820:             * <p>This client pool does a lot of nice thinigs, but could probably be
0821:             * implemented in a much better way (while keeping the features it has).
0822:             * Contention arond the pool is probably concern number 1 of performances.
0823:             * @param socket The connection to handle.
0824:             */
0825:
0826:            public void handleConnection(Socket socket) {
0827:                if (debug)
0828:                    System.out.println("new connection.");
0829:                SocketClientState cs = null;
0830:                switch (loadavg) {
0831:                case AVG_LIGHT:
0832:                    // Free list is non empty, be fast:
0833:                    if (decrFreeCount()) {
0834:                        cs = (SocketClientState) freeList.removeTail();
0835:                        if (cs == null) {
0836:                            while (!incrFreeCount()) {
0837:                            }
0838:                        }
0839:                    }
0840:                    break;
0841:                case AVG_NORMAL:
0842:                case AVG_HIGH:
0843:                    // Free list is non empty, but we try killing a client:
0844:                    killSomeClients();
0845:                    if (decrFreeCount()) {
0846:                        cs = (SocketClientState) freeList.removeTail();
0847:                        if (cs == null) {
0848:                            while (!incrFreeCount()) {
0849:                            }
0850:                        }
0851:                    }
0852:                    break;
0853:                case AVG_DEAD:
0854:                    break;
0855:                }
0856:                if (debug)
0857:                    System.out
0858:                            .println("load "
0859:                                    + loadavg
0860:                                    + ", client="
0861:                                    + ((cs != null) ? cs.client.toString()
0862:                                            : "unbound"));
0863:                // At this point, we do have a free client, bind it:
0864:                if (cs != null) {
0865:                    if (debug)
0866:                        System.out.println(cs.client + ": bound.");
0867:                    cs.status = SocketClientState.C_BUSY;
0868:                    cs.client.bind(socket);
0869:                } else {
0870:                    if (debug)
0871:                        System.out
0872:                                .println("*** connection refused (overloaded).");
0873:                    try {
0874:                        socket.close();
0875:                    } catch (IOException ex) {
0876:                    }
0877:                    server.errlog(socket.getInetAddress()
0878:                            + " refused (overloaded).");
0879:                }
0880:                return;
0881:            }
0882:
0883:            protected synchronized void killClients(boolean force) {
0884:                alive = false;
0885:                // Kill all clients (first shot):
0886:                SocketClientState cs = csList;
0887:                while ((cs != null) && (cs.client != null)) {
0888:                    synchronized (csList) {
0889:                        // Only if a client is idely read'ing its socket, we close it
0890:                        cs.client.kill(cs.status == SocketClientState.C_IDLE);
0891:                    }
0892:                    cs = cs.csnext;
0893:                }
0894:                // Kill all clients (second shot):
0895:                // Some client may be in transition during first shot, second shot
0896:                // really kills everything.
0897:                try {
0898:                    Thread.sleep(5000);
0899:                } catch (Exception ex) {
0900:                }
0901:                cs = csList;
0902:                while ((cs != null) && (cs.client != null)) {
0903:                    synchronized (csList) {
0904:                        cs.client.kill(true);
0905:                    }
0906:                    cs = cs.csnext;
0907:                }
0908:            }
0909:
0910:            /**
0911:             * Shutdown the client pool. 
0912:             * If force is <strong>true</strong>, kill all running clients right
0913:             * now, otherwise, wait for them to terminate gracefully, and return
0914:             * when done.
0915:             * @param force Should we interrupt running clients.
0916:             */
0917:
0918:            public void shutdown(boolean force) {
0919:                // First stage: kill all clients (synchronized)
0920:                killClients(force);
0921:                // Second stage (unsynchronized), join all client threads
0922:                SocketClientState cs = csList;
0923:                while ((cs != null) && (cs.client != null)) {
0924:                    if (debug)
0925:                        System.out.println(cs.client + ": join.");
0926:                    cs.client.join();
0927:                    cs = cs.csnext;
0928:                }
0929:                // Some cleanup (helps the GC, and make sure everything is free)
0930:                props.unregisterObserver(this );
0931:                props = null;
0932:                csList = null;
0933:                freeList = null;
0934:                idleList = null;
0935:                server = null;
0936:            }
0937:
0938:            /**
0939:             * Create the master socket for this client factory.
0940:             * @exception IOException If some IO error occurs while creating the
0941:             * server socket.
0942:             * @return A ServerSocket instance.
0943:             */
0944:
0945:            public ServerSocket createServerSocket() throws IOException {
0946:                // using maxCLient in the backlog is safe, but an overkill :)
0947:                if (bindAddr == null) {
0948:                    return new ServerSocket(server.getPort(), Math.max(128,
0949:                            maxClients));
0950:                } else {
0951:                    return new ServerSocket(server.getPort(), Math.max(128,
0952:                            maxClients), bindAddr);
0953:                }
0954:            }
0955:
0956:            /**
0957:             * Initialize the raw, client socket factory.
0958:             * @param server The server context we are attached to.
0959:             */
0960:
0961:            public void initialize(httpd server) {
0962:                // Initialize instance variables:
0963:                this .server = server;
0964:                this .props = server.getProperties();
0965:                this .props.registerObserver(this );
0966:                // Register our property sheet:
0967:                PropertySet set = new SocketConnectionProp(
0968:                        "SocketConnectionProp", server);
0969:                server.registerPropertySet(set);
0970:                // Initialize parameters from properties:
0971:                this .minFree = props.getInteger(MINSPARE_FREE_P, MINSPARE_FREE);
0972:                this .maxFree = props.getInteger(MAXSPARE_FREE_P, MAXSPARE_FREE);
0973:                this .maxIdle = props.getInteger(MAXSPARE_IDLE_P, MAXSPARE_IDLE);
0974:                this .maxClients = props.getInteger(MAXCLIENTS_P, MAXCLIENTS);
0975:                this .timeout = props.getInteger(TIMEOUT_P, IDLETO);
0976:                String bindAddrName = props.getString(BINDADDR_P, null);
0977:                if (bindAddrName != null) {
0978:                    try {
0979:                        bindAddr = InetAddress.getByName(bindAddrName);
0980:                    } catch (Exception ex) {
0981:                        // nothing, fallback to default
0982:                    }
0983:                }
0984:                // Create the LRU lists:
0985:                idleList = new SyncLRUList();
0986:                freeList = new SyncLRUList();
0987:                // Create the full client list:
0988:                csList = new SocketClientState();
0989:                // Create all our clients:
0990:                for (int i = 0; i < maxClients; i++) {
0991:                    if (addClient(true) == null)
0992:                        throw new RuntimeException(this .getClass().getName()
0993:                                + "[construstructor]"
0994:                                + ": unable to create clients.");
0995:                }
0996:                // Create the thread cache:
0997:                threadcache = new ThreadCache(server.getIdentifier()
0998:                        + "-socket-clients");
0999:                threadcache.setCachesize(props.getInteger(MAXTHREADS_P,
1000:                        MAXTHREADS));
1001:                threadcache.setThreadPriority(server.getClientThreadPriority());
1002:                threadcache.setIdleTimeout(props.getInteger(IDLETO_P, IDLETO));
1003:                threadcache.setGrowAsNeeded(true);
1004:                threadcache.initialize();
1005:                // Start the debugging thread, if needed:
1006:                if (debugthread) {
1007:                    new DebugThread(this ).start();
1008:                }
1009:            }
1010:
1011:            /**
1012:             * Empty constructor for dynamic class instantiation.
1013:             */
1014:
1015:            public SocketClientFactory() {
1016:            }
1017:
1018:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.