⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 socketclientfactory.java

📁 很棒的web服务器源代码
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
     * <strong>AVG_DEAD</strong>. This ensures that the server will start      * dropping connections.     *     */    private final void updateLoadAverage() {	int oldavg = loadavg;	if ( freeCount >= maxFree ) {	    loadavg = AVG_LIGHT;	} else if ((freeCount >= minFree) || (idleCount >= maxIdle)) {	    if ((loadavg = AVG_NORMAL) < oldavg) {		server.thread.setPriority(Thread.MAX_PRIORITY);	    }	} else if ( freeCount > 0 ) {	    /* idleCount < MINSPARE_IDLE */	    if ((loadavg = AVG_HIGH) > oldavg) {		// first ensure the state is sane//		checkDeadClients();		server.thread.setPriority(server.getClientThreadPriority()-2);	    }	} else {	    loadavg = AVG_DEAD;	}    }	        private final synchronized void incrClientCount() {	++clientCount;	++clientEstim;	updateLoadAverage();    }    private final synchronized void decrClientCount() {	--clientCount;	updateLoadAverage();    }    private final synchronized boolean incrFreeCount() {	if ( clientEstim > maxClients ) {	    clientEstim--;	    return false;	}	++freeCount;	updateLoadAverage();	return true;    }    private final synchronized boolean decrFreeCount() {	if ( freeCount > 0 ) {	    --freeCount;	    updateLoadAverage();	    return true;	} else {	    return false;	}    }    private final synchronized boolean incrIdleCount() {	if ((loadavg > AVG_HIGH) || (idleCount + 1 >= maxIdle))	    return false;	++idleCount;	updateLoadAverage();	return true;    }    private final synchronized boolean decrIdleCount() {	if ( idleCount > 0 ) {	    --idleCount;	    updateLoadAverage();	    return true;	} else {	    return false;	}    }    /**     * Removes an idle client from the list, updates only the idle list     * as the free count has already be accessed     * @param the socket client to remove from the idle list     */    protected boolean idleClientRemove(SocketClient client) {	// If the client pool has shut down, exit straight:	if ( ! alive )	    return false;	SocketClientState cs = client.state;	synchronized (cs) {	    switch(cs.status) {	    case SocketClientState.C_IDLE:		decrIdleCount();		idleList.remove(cs);		cs.status = SocketClientState.C_FREE;		break;	    case SocketClientState.C_KILL:	    case SocketClientState.C_BUSY:	    default:		break;	    }	}	return true;    }	    /**     * Notify that this client has finished with its connection.     * If the pool wants the client to be freed (because it has too many of      * them), it makes the client kill itself (which will trigger a call to     * the clientFinished method, were enventual cleanup is performed).     * @param client The client that is done with its connection.     */    protected boolean clientConnectionFinished (SocketClient client) {	// If the client pool has shut down, exit straight:	if ( ! alive )	    return false;	SocketClientState cs = client.state;	synchronized (cs) {    	    switch(cs.status) {	    case SocketClientState.C_IDLE:		decrIdleCount();		idleList.remove(cs);		break;	    case SocketClientState.C_BUSY:	    case SocketClientState.C_KILL:		break;	    case SocketClientState.C_FREE:		// already freeed?		if (client.done) {		    client.done = false;		    return true;		}	    default:		break;	    }	    if (incrFreeCount()) {		if ( debug )		    System.out.println(client+": now free.");		cs.status = SocketClientState.C_FREE;		freeList.toHead(cs);		return true;	    } else {		if ( debug )		    System.out.println(client+": terminate.");		return false;	    }	}    }    /**     * Notify that this client has been killed.     * @param client The client that has terminate.     */    protected void clientFinished (SocketClient client) {	// If we're not alive any more, skip:	if ( ! alive )	    return;	SocketClientState cs = client.state;	synchronized (cs) {	    if ( debug )		System.out.println(client+": finished "+cs.status);	    // Otherwise, perform the job:	    switch(cs.status) {	    case SocketClientState.C_IDLE:		break;	    case SocketClientState.C_FREE:		decrFreeCount();		freeList.remove(cs);		break;	    case SocketClientState.C_BUSY:	    default:		String msg = (client 			      + ": finished with unknown status "			      + cs.status);		server.errlog(msg);		break;	    }	    cs.status = SocketClientState.C_FIN;	    decrClientCount();	    deleteClient(cs);	}    }    /**     * The client notifies the pool that is has been activated.     * The client state object is updated to unmark the client as idle.     * <p>This method needs not be synchronized, as it affect only the client     * state, <em>not</em> the client list.     * @param client The activated client.     */    protected void notifyUse(SocketClient client) {	if ( debug )	    System.out.println(client+": used.");	SocketClientState cs = client.state;	synchronized (cs) {	    if (cs.status == SocketClientState.C_IDLE) {		decrIdleCount();		idleList.remove(cs);	    }	    cs.status = SocketClientState.C_BUSY;	}    }    /**     * The client notifies the pool that it enters idle state.     * <p>This method needs not be synchronized, as it affect only the client     * state, <em>not</em> the client list.     * @param client The client that is going to be idle.     */    protected boolean notifyIdle(SocketClient client) {	SocketClientState cs = client.state;	if ( alive ) {	    synchronized (cs) {		if ( incrIdleCount() ) {		    if ( debug ) 			System.out.println(client+": idle, keep-alive.");		    cs.status = SocketClientState.C_IDLE;		    idleList.toHead(cs);		    return true;		} else {		    if ( debug )			System.out.println(client+": idle, closed.");		    // Kill some old idle connections, give a chance for next:		    int killsome = Math.max((maxFree - freeCount), 					    (maxIdle - idleCount));		    killSomeClients((killsome > 0) ? killsome : 1);		    // And give it a change if the load is not too high		    if ( incrIdleCount() ) {			if ( debug ) 			    System.out.println(client+": idle, keep-alive.");			cs.status = SocketClientState.C_IDLE;			idleList.toHead(cs);			return true;			    } 		    return false;		}	    }	} else {	    if ( debug )		System.out.println(client+": idle (dead), closed.");	    // Kill some old idle connections, give a chance for next:	    int killsome = Math.max((maxFree - freeCount),				    (maxIdle - idleCount));	    killSomeClients((killsome > 0) ? killsome : 1);	    return false;	}    }    protected void killSomeClients(int howmany) {	int count = (howmany > 0) ? howmany : Math.max((maxFree - freeCount),						       (maxIdle - idleCount));	if (debug) {	    System.out.println("Killing :" + howmany);	}	while ( --count >= 0 ) {	    SocketClientState cs = (SocketClientState) idleList.removeTail();	    if ( cs != null ) {		synchronized (cs) {		    if (cs.status == SocketClientState.C_IDLE) {			if ( debug )			    System.out.println(cs.client + 					       ": kill (some-client).");			decrIdleCount();			cs.status = SocketClientState.C_KILL;			cs.client.unbind();		    }		}	    } else {		break;	    }	    // if the load falls back to normal operation, we are all set	    if ((freeCount > minFree) && (idleCount < maxIdle)) {		break;	    }	}    }    final protected void killSomeClients() {	killSomeClients(-1);    }    protected void run(SocketClient client) {	if ( debug )	    System.out.println(client+": warming up...");	boolean threaded = threadcache.getThread(client, true);	if ( debug )	    System.out.println(client+": threaded="+threaded);    }    /**     * Handle the given connection.     * Find a free client, bind it to the given socket, and run it. If we     * have reached our maximum allowed number of clients, kill some     * connections.     * <p>A client enters the LRU list (and become a candidate for kill) only     * after it has handle one request (or if some timeout expires). This is     * performed by the first call to <code>notifyUse</code> which will     * silently insert the client into the LRU if it was not there already.     * <p>This client pool does a lot of nice thinigs, but could probably be     * implemented in a much better way (while keeping the features it has).     * Contention arond the pool is probably concern number 1 of performances.     * @param socket The connection to handle.     */    public void handleConnection (Socket socket) {	if ( debug )	    System.out.println("new connection.");	SocketClientState cs = null;	switch(loadavg) {	  case AVG_LIGHT:	      // Free list is non empty, be fast:	      if ( decrFreeCount() )		  cs = (SocketClientState) freeList.removeTail();	      break;	  case AVG_NORMAL:	  case AVG_HIGH:	      // Free list is non empty, but we try killing a client:	      killSomeClients();	      if ( decrFreeCount() ) {		  cs = (SocketClientState) freeList.removeTail();	      }	      break;	  case AVG_DEAD:	      break;	}	if ( debug )	    System.out.println("load "+loadavg			       + ", client="			       + ((cs != null) 				  ? cs.client.toString()				  : "unbound"));	// At this point, we do have a free client, bind it:	if ( cs != null ) {	    if ( debug ) 		System.out.println(cs.client+": bound.");	    cs.status = SocketClientState.C_BUSY;	    cs.client.bind(socket);	} else {	    if ( debug )		System.out.println("*** connection refused (overloaded).");	    try {		socket.close();	    } catch (IOException ex) {	    }	    server.errlog(socket.getInetAddress()+" refused (overloaded).");	}	return;    }    protected synchronized void killClients(boolean force) {	alive = false;	// Kill all clients (first shot):	SocketClientState cs = csList;	while ((cs != null) && (cs.client != null)) {	    synchronized (cs) {		// Only if a client is idely read'ing its socket, we close it		cs.client.kill(cs.status==SocketClientState.C_IDLE);	    }	    cs = cs.csnext;	}	// Kill all clients (second shot):	// Some client may be in transition during first shot, second shot	// really kills everything.	try {	    Thread.sleep(5000);	} catch (Exception ex) {	}	cs = csList;	while ((cs != null) && (cs.client != null)) {	    synchronized (cs) {		cs.client.kill(true);	    }	    cs = cs.csnext;	}    }    /**     * Shutdown the client pool.      * If force is <strong>true</strong>, kill all running clients right     * now, otherwise, wait for them to terminate gracefully, and return     * when done.     * @param force Should we interrupt running clients.     */    public void shutdown (boolean force) {	// First stage: kill all clients (synchronized)	killClients(force) ;	// Second stage (unsynchronized), join all client threads	SocketClientState cs = csList;	while ((cs != null) && (cs.client != null)) {	    if ( debug )		System.out.println(cs.client+": join."); 	    cs.client.join();	    cs = cs.csnext;	}	// Some cleanup (helps the GC, and make sure everything is free)	props.unregisterObserver(this);	props    = null;	csList   = null;	freeList = null;	idleList = null;	server   = null;    }    /**     * Create the master socket for this client factory.     * @exception IOException If some IO error occurs while creating the     * server socket.     * @return A ServerSocket instance.     */    public ServerSocket createServerSocket() 	throws IOException    {	// using maxCLient in the backlog is safe, but an overkill :)	if (bindAddr == null) {	    return new ServerSocket (server.getPort(),				     Math.max(128, maxClients));	} else {	    return new ServerSocket (server.getPort(), 				     Math.max(128, maxClients),				     bindAddr);	}    }    /**     * Initialize the raw, client socket factory.     * @param server The server context we are attached to.     */    public void initialize(httpd server) {	// Initialize instance variables:	this.server = server ;	this.props  = server.getProperties() ;	this.props.registerObserver (this) ;	// Register our property sheet:	PropertySet set = new SocketConnectionProp("SocketConnectionProp"						   , server);	server.registerPropertySet(set);	// Initialize parameters from properties:	this.minFree    = props.getInteger(MINSPARE_FREE_P, MINSPARE_FREE);	this.maxFree    = props.getInteger(MAXSPARE_FREE_P, MAXSPARE_FREE);	this.maxIdle    = props.getInteger(MAXSPARE_IDLE_P, MAXSPARE_IDLE);	this.maxClients = props.getInteger(MAXCLIENTS_P, MAXCLIENTS);	String bindAddrName = props.getString(BINDADDR_P, null);	if (bindAddrName != null) {	    try {		bindAddr = InetAddress.getByName(bindAddrName);	    } catch (Exception ex) {		// nothing, fallback to default	    }	}	// Create the LRU lists:	idleList = new SyncLRUList();	freeList = new SyncLRUList();	// Create the full client list:	csList = new SocketClientState();	// Create all our clients:	for (int i = 0 ; i < maxClients ; i++) {	    if ( addClient(true) == null )		throw new RuntimeException (this.getClass().getName()					    + "[construstructor]"					    + ": unable to create clients.");	}	// Create the thread cache:	threadcache = new ThreadCache(server.getIdentifier() + 				      "-socket-clients");	threadcache.setCachesize(props.getInteger(MAXTHREADS_P, MAXTHREADS));	threadcache.setThreadPriority(server.getClientThreadPriority());	threadcache.setIdleTimeout(props.getInteger(IDLETO_P,IDLETO));	threadcache.setGrowAsNeeded(true);	threadcache.initialize();	// Start the debugging thread, if needed:	if ( debugthread ) {	    new DebugThread(this).start();	}    }    /**     * Empty constructor for dynamic class instantiation.     */    public SocketClientFactory() {    }}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -