All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.xsocket.connection.IoSocketDispatcherPool Maven / Gradle / Ivy

There is a newer version: 2.8.15
Show newest version
/*
 * Copyright (c) xlightweb.org, 2006 - 2010. All rights reserved.
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License as published by the Free Software Foundation; either
 *  version 2.1 of the License, or (at your option) any later version.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * Please refer to the LGPL license at: http://www.gnu.org/copyleft/lesser.txt
 * The latest copy of this software may be found on http://www.xsocket.org/
 */
package org.xsocket.connection;


import java.io.Closeable;
import java.io.IOException;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;



/**
 * Dispacher pool
 * 
 *
 * @author [email protected]
 */
final class IoSocketDispatcherPool implements Closeable {

	private static final Logger LOG = Logger.getLogger(IoSocketDispatcherPool.class.getName());
	
    
    // open flag
    private volatile boolean isOpen = true;

    // name 
    private final String name;

    
	// listeners
	private final ArrayList listeners = new ArrayList();

    
	// memory management
	private int preallocationSize = IoProvider.DEFAULT_READ_BUFFER_PREALLOCATION_SIZE;
	private int bufferMinsize = IoProvider.DEFAULT_READ_BUFFER_MIN_SIZE;
	private boolean preallocation = true; 
	private boolean useDirect = false;

 
	// dispatcher management
	private final LinkedList dispatchers = new LinkedList();
	private int size;
	private int pointer;

    
	
    // statistics
    private long acceptedConnections;
	private long lastRequestAccpetedRate = System.currentTimeMillis();


	public IoSocketDispatcherPool(String name, int size) {
		this.name = name;
		setDispatcherSize(size);
    }
    

    void addListener(IIoDispatcherPoolListener listener) {
		listeners.add(listener);
	}


	boolean removeListener(IIoDispatcherPoolListener listener) {
		return listeners.remove(listener);
	}



	IoSocketDispatcher nextDispatcher() throws IOException {
		return nextDispatcher(0);
	}
	
	
	private IoSocketDispatcher nextDispatcher(int currentTrial) throws IOException {
		IoSocketDispatcher dispatcher = null;
		
		if (!isOpen) {
		    throw new IOException("dispatcher is already closed");
		}
		
		try {
			// round-robin approach
			pointer++;
			if (pointer >= size) { // unsynchronized access of size is OK here (findbugs will criticize this)
				pointer = 0;
			}
	
			dispatcher = dispatchers.get(pointer);
			boolean peregistered = dispatcher.preRegister();
			
			if (peregistered) {
				return dispatcher;
				
			} else {
				if (currentTrial < size) {
					return nextDispatcher(++currentTrial);
				} else {
					if (LOG.isLoggable(Level.FINE)) {
						LOG.fine("increasing dispatcher size because max handle size " + dispatcher.getMaxRegisterdHandles() + " of all " + size + " dispatcher reached");
					}
					incDispatcherSize();
					return nextDispatcher(0);
				}
			}
			
		} catch (Exception concurrentException) {
			if (isOpen) {
				if (currentTrial < 3) {
					dispatcher = nextDispatcher(++currentTrial);
				} else {
					throw new IOException(concurrentException.toString());
				}
			} 
		}
		
		return dispatcher;
	}
	
	
	
	

	private synchronized void updateDispatcher() {
		if (isOpen) {
			synchronized (dispatchers) {
				int currentRunning = dispatchers.size();
	
				if (currentRunning != size) {
					if (currentRunning > size) {
						for (int i = size; i <  currentRunning; i++) {
							IoSocketDispatcher dispatcher = dispatchers.getLast();
							dispatchers.remove(dispatcher);
							try {
								dispatcher.close();
							} catch (IOException ioe) {
								if (LOG.isLoggable(Level.FINE)) {
									LOG.fine("error occured by closing the dispatcher " + dispatcher + ". reason " + ioe.toString());
								}
							}
	
							for (IIoDispatcherPoolListener listener : listeners) {
								listener.onDispatcherRemoved(dispatcher);
							}
						}
	
					} else if ( currentRunning < size) {
						for (int i = currentRunning; i < size; i++) {
							IoUnsynchronizedMemoryManager memoryManager = null;
							if (preallocation) {
								memoryManager = IoUnsynchronizedMemoryManager.createPreallocatedMemoryManager(preallocationSize, bufferMinsize, useDirect);
							} else {
								memoryManager = IoUnsynchronizedMemoryManager.createNonPreallocatedMemoryManager(useDirect);
							}
							
							IoSocketDispatcher dispatcher = new IoSocketDispatcher(memoryManager, name + "#" + i);
							dispatchers.addLast(dispatcher);
	
							Thread t = new Thread(dispatcher);
							t.setDaemon(true);
							t.start();
	
							for (IIoDispatcherPoolListener listener : listeners) {
								listener.onDispatcherAdded(dispatcher);
							}
	
						}
					}
				}
	
				IoSocketDispatcher[] connectionDispatchers = new IoSocketDispatcher[dispatchers.size()];
				for (int i = 0; i < connectionDispatchers.length; i++) {
					connectionDispatchers[i] = dispatchers.get(i);
				}
			}
		}
	}


    

    /**
     * {@inheritDoc}
     */
    public void close() throws IOException {
        if (isOpen) {
            isOpen = false;

            shutdownDispatcher();
        }
    }

    
    

	/**
	 * shutdown the pool
	 *
	 */
	private void shutdownDispatcher() {
        if (LOG.isLoggable(Level.FINER)) {
			LOG.fine("terminate dispatchers");
		}

        synchronized (dispatchers) {
			for (IoSocketDispatcher dispatcher : dispatchers) {
				try {
					dispatcher.close();
	
					for (IIoDispatcherPoolListener listener : listeners) {
						listener.onDispatcherRemoved(dispatcher);
					}
	
				} catch (IOException ioe) {
					if (LOG.isLoggable(Level.FINE)) {
						LOG.fine("error occured by closing the dispatcher " + dispatcher + ". reason " + ioe.toString());
					}
				}
	        }
        }

		dispatchers.clear();
	}

	
	int getNumRegisteredHandles() {
	    int num = 0;
	    for (IoSocketDispatcher dispatcher : getDispatchers()) {
	        num += dispatcher.getNumRegisteredHandles();
        }
	    return num;
	}

	    
	int getRoughNumRegisteredHandles() {
        int num = 0;
        for (IoSocketDispatcher dispatcher : getDispatchers()) {
            num += dispatcher.getRoughNumRegisteredHandles();
        }
        return num;
	}


    
    public List getOpenConntionInfos() {
    	List result = new ArrayList();
    	
        for (IoSocketDispatcher dispatcher : getDispatchers()) {
            for (IoSocketHandler handler : dispatcher.getRegistered()) {
                result.add(handler.toString());
            }
        }
        return result;
    }
    
    
	@SuppressWarnings("unchecked")
	List getDispatchers() {
		List result = null;
		synchronized (dispatchers) {
			result = (List) dispatchers.clone();
		}
		return result;
	}

    
	
	synchronized void setDispatcherSize(int size) {
    	this.size = size;
		updateDispatcher();
    }
    
	synchronized int getDispatcherSize() {
    	return size;
    }
	
	synchronized void incDispatcherSize() {
    	setDispatcherSize(getDispatcherSize() + 1);
    }
	

    
	boolean getReceiveBufferIsDirect() {
		return useDirect;
	}

	void setReceiveBufferIsDirect(boolean isDirect) {
		this.useDirect = isDirect; 
		for (IoSocketDispatcher dispatcher: dispatchers) {
			dispatcher.setReceiveBufferIsDirect(isDirect);
		}
	}

	
	boolean isReceiveBufferPreallocationMode() {
    	return preallocation;
	}
	    
	void setReceiveBufferPreallocationMode(boolean mode) {
		this.preallocation = mode;

		synchronized (dispatchers) {
			for (IoSocketDispatcher dispatcher: dispatchers) {
				dispatcher.setReceiveBufferPreallocationMode(mode);
			}
		}
	}
	
	void setReceiveBufferPreallocatedMinSize(Integer minSize) {
		this.bufferMinsize = minSize;
		
		synchronized (dispatchers) {
			for (IoSocketDispatcher dispatcher: dispatchers) {
				dispatcher.setReceiveBufferPreallocatedMinSize(minSize);
			}
		}
	}
	
	
	Integer getReceiveBufferPreallocatedMinSize() {
   		return bufferMinsize;
 	}
	
	
	
	/**
	 * get the size of the preallocation buffer,
	 * for reading incoming data
	 *
	 * @return preallocation buffer size
	 */
	Integer getReceiveBufferPreallocationSize() {
		return preallocationSize;
	}

	/**
	 * set the size of the preallocation buffer,
	 * for reading incoming data
	 *
	 * @param size the preallocation buffer size
	 */
	void setReceiveBufferPreallocationSize(int size) {
		preallocationSize = size;
		
		for (IoSocketDispatcher dispatcher: dispatchers) {
			dispatcher.setReceiveBufferPreallocatedSize(size);
		}
	}


	  
    double getAcceptedRateCountPerSec() {
     	double rate = 0;
		
    	long elapsed = System.currentTimeMillis() - lastRequestAccpetedRate;
    	
    	if (acceptedConnections == 0) {
    		rate = 0;
    		
    	} else if (elapsed == 0) {
    		rate = Integer.MAX_VALUE;
    		
    	} else {
    		rate = (((double) (acceptedConnections * 1000)) / elapsed);
    	}
    		
    	lastRequestAccpetedRate = System.currentTimeMillis();
    	acceptedConnections = 0;

    	return rate;
    }
    
	
	long getSendRateBytesPerSec() {
		long rate = 0;
		for (IoSocketDispatcher dispatcher : dispatchers) {
			rate += dispatcher.getSendRateBytesPerSec();
		}
		
		return rate;
	}
	
	
	long getReceiveRateBytesPerSec() {
		long rate = 0;
		for (IoSocketDispatcher dispatcher : dispatchers) {
			rate += dispatcher.getReceiveRateBytesPerSec();
		}
		
		return rate;
	}
	


	@SuppressWarnings("unchecked")
	long getNumberOfConnectionTimeouts() {
		long timeouts = 0;

		LinkedList copy = null;
		synchronized (dispatchers) {
			copy = (LinkedList) dispatchers.clone();
		}
		for (IoSocketDispatcher dispatcher : copy) {
			timeouts += dispatcher.getCountConnectionTimeout();
		}
		return timeouts;
	}


	@SuppressWarnings("unchecked")
	public long getNumberOfIdleTimeouts() {
		long timeouts = 0;

		LinkedList copy = null;
		synchronized (dispatchers) {
			copy = (LinkedList) dispatchers.clone();
		}
		for (IoSocketDispatcher dispatcher : copy) {
			timeouts += dispatcher.getCountIdleTimeout();
		}
		return timeouts;
	}


}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy